18. marts 2007 - 13:19Der er
39 kommentarer og 2 løsninger
VBA+kopiere ark til en anden Excel-fil
Hejsa
Kan man lave en makro som ved aktivering kopierer alle 4 ark fra en særskilt Excel-fil(data.xls) til den pågældende Excel-fil man aktiverer makroen i ?
Og muligvis samtidig sætter dem til skjult
P.S. Det er meget vigtigt at der ikke er nogen kæde til den Excel-fil arkene kopieres fra.
Const stiData = "C:\Documents and Settings\pb\Skrivebord\1803KopierArk\data.xls" 'Tilpasses Dim xls As Object Sub kopierData() Set xls = CreateObject("Excel.Application") With xls .Workbooks.Open stiData
For ark = 1 To 4 .ActiveWorkbook.Sheets(ark).Activate .Cells.Copy ActiveWorkbook.Sheets.Add before:=ActiveWorkbook.Sheets(ark) ActiveSheet.Paste Destination:=Worksheets(ark).Range("A1") Next ark End With
xls.Quit Set xls = Nothing End Sub
PS: mangler lidt til kode til at slette udklipsholder - vender tilbage med denne
Har endnu ikke fundet midlet - men prøver... Ja - det kan de godt Ja - så vil det nemlig ideelt, at ArkNavne overføres - og så slette dem, hvis de eksisterer i forvejen.
Const stiData = "C:\Documents and Settings\pb\Skrivebord\1803KopierArk_MiRa\data.xls" 'Tilpasses Dim xls As Object Sub kopierData() Set xls = CreateObject("Excel.Application") With xls .Workbooks.Open stiData
For ark = 1 To 4 .ActiveWorkbook.Sheets(ark).Activate .Cells.Copy
ActiveWorkbook.Sheets.Add before:=ActiveWorkbook.Sheets(ark) ActiveSheet.Paste Destination:=Worksheets(ark).Range("A1") ActiveSheet.Name = .ActiveWorkbook.Sheets(ark).Name Next ark End With
xls.Application.DisplayAlerts = False xls.Quit Set xls = Nothing
Application.DisplayAlerts = True End Sub Private Sub testOmArkFindes(ark) For Each a In ActiveWorkbook.Sheets If a.Name = ark Then a.Delete End If Next a End Sub
Men hvorfor bliver min datafil (data.xls) skrivebeskyttet ? Den vedbliver at være skrivebeskyttet også efter jeg lukker Excel.
Her er min kode i ThisWorkbook:
Const stiData = "C:\Rødvig\Data.xls" 'Tilpasses Dim xls As Object Private Sub Workbook_Open() Set xls = CreateObject("Excel.Application") With xls .Workbooks.Open stiData
For ark = 1 To 4 .ActiveWorkbook.Sheets(ark).Activate .Cells.Copy
ActiveWorkbook.Sheets.Add before:=ActiveWorkbook.Sheets(ark) ActiveSheet.Paste Destination:=Worksheets(ark).Range("A1") ActiveSheet.Name = .ActiveWorkbook.Sheets(ark).Name ActiveSheet.Visible = False Next ark End With
xls.Application.DisplayAlerts = False xls.Quit Set xls = Nothing If Right(LCase(ActiveWorkbook.Name), 3) <> "xls" Then Load UserForm4 UserForm4.Show End If Application.DisplayAlerts = True End Sub Private Sub testOmArkFindes(ark) For Each a In ActiveWorkbook.Sheets If a.Name = ark Then a.Delete End If Next a End Sub
Her er min kode i Userform4:
Rem Version 5 Rem ========= Const DataSti = "C:\Rødvig\Data.xls" 'tilpasses Const gemSomSti = "C:\Rødvig\Tilbud\" 'tilpasses Dim rækIArk, aktuelleRæk Dim dataarkXLS As Object, kXLS As Object, passFlag As Boolean
Private Sub udførGem() Dim sti As String, gemMappe As String, uMappe As String
Rem check drev On Error GoTo sti_Fejl
sti = gemSomSti If Right(sti, 1) <> "\" Then sti = sti + "\" End If
Rem KundeMappe Ok - gem filen On Error GoTo fejlGemSti ActiveWorkbook.SaveAs sti + "Tilbud " + f_projekt + " " + Me.f_kundeNr + ".xls"
Rem Luk userform CommandButton2_Click 'kan fjernes, hvis lukning ikke ønskes Exit Sub
fejlGemSti: MsgBox ("Fejl i GemSti - sandsynligvis illegalt tegn i årstal") Exit Sub
sti_Fejl: MsgBox ("Fejl i en sti-angivelse") End Sub
Private Sub f_kundeNr_Enter() Me.f_kundeNavn = ""
End Sub Private Sub f_kundeNr_Exit(ByVal Cancel As MSForms.ReturnBoolean) If passFlag = False Then passFlag = True If Me.f_kundeNr <> "" And IsNumeric(Me.f_kundeNr) = True Then Me.f_kundeNavn = søgKunde(Val(Me.f_kundeNr)) Me.f_adresse = søgKundeA(Val(Me.f_kundeNr)) Me.f_postnr = søgKundeP(Val(Me.f_kundeNr)) Me.f_by = søgKundeB(Val(Me.f_kundeNr))
If Me.f_kundeNavn <> "" Then Me.f_kundeNr.SetFocus End If
kXLS.Quit Set kXLS = Nothing End If passFlag = False End If End Sub Private Sub CommandButton2_Click() 'Annuller Unload UserForm4 End Sub
Private Function søgKunde(kNr) Set kXLS = CreateObject("Excel.application") With kXLS .Workbooks.Open DataSti .Sheets(1).Activate Max = .ActiveCell.SpecialCells(xlLastCell).Row For r = 1 To Max If .Cells(r, 1) = kNr Then søgKunde = .Cells(r, 2) Exit Function End If Next r End With søgKunde = "" MsgBox ("Det indtastede kundenr. kunne ikke findes") End Function Private Function søgKundeA(kNr) Set kXLS = CreateObject("Excel.application") With kXLS .Workbooks.Open DataSti .Sheets(1).Activate Max = .ActiveCell.SpecialCells(xlLastCell).Row For r = 1 To Max If .Cells(r, 1) = kNr Then søgKundeA = .Cells(r, 3) Exit Function End If Next r End With søgKundeA = "" MsgBox ("Det indtastede kundenr. kunne ikke findes") End Function Private Function søgKundeP(kNr) Set kXLS = CreateObject("Excel.application") With kXLS .Workbooks.Open DataSti .Sheets(1).Activate Max = .ActiveCell.SpecialCells(xlLastCell).Row For r = 1 To Max If .Cells(r, 1) = kNr Then søgKundeP = .Cells(r, 4) Exit Function End If Next r End With søgKundeP = "" MsgBox ("Det indtastede kundenr. kunne ikke findes") End Function Private Function søgKundeB(kNr) Set kXLS = CreateObject("Excel.application") With kXLS .Workbooks.Open DataSti .Sheets(1).Activate Max = .ActiveCell.SpecialCells(xlLastCell).Row For r = 1 To Max If .Cells(r, 1) = kNr Then søgKundeB = .Cells(r, 5) Exit Function End If Next r End With søgKundeB = "" MsgBox ("Det indtastede kundenr. kunne ikke findes") End Function Private Function findGemMappe(sti, kNr) Rem Søger efter mappe med navnet: Kundenr+BLANK i begyndelsen af MappeNavnet Dim fs, f, f1, fc, s, xKnr kNr = CStr(Val(kNr)) 'fjerner foranstillede nuller
Set fs = CreateObject("Scripting.FileSystemObject") Set f = fs.GetFolder(sti) Set fc = f.SubFolders For Each f1 In fc If InStr(f1.Name, kNr + " ") = 1 Or InStr(f1.Name, kNr) = 1 Then findGemMappe = f1.Name 'Fulde mappeNavn returneres.. Exit Function End If Next findGemMappe = "" End Function Private Sub UserForm_activate() indlæsprojekt Me.f_kundeNr.SetFocus End Sub Private Sub indlæsprojekt() On Error GoTo fejlprojektSti
Set dataarkXLS = CreateObject("Excel.application") With dataarkXLS .Workbooks.Open DataSti .Sheets(3).Activate Max = .ActiveCell.SpecialCells(xlLastCell).Row For r = 5 To Max Me.f_projekt.AddItem .Cells(r, 1) Next r End With
dataarkXLS.Quit Set dataarkXLS = Nothing Exit Sub
fejlprojektSti: MsgBox ("Fejl i sti t/projekt.xls") End Sub
Private Sub CommandButton1_Click()
If Me.f_kundeNr.Value <> "" And _ Me.f_projekt.Value <> "" Then
OpdaterIArk udførGem Else MsgBox ("Alle felter skal udfyldes") End If End Sub
I stedet for at den sletter arkene hvis de findes i forvejen. Kan den så ikke overskrive dem.
Grunden er at jeg har foruddefinerede områder i mit data-ark som bruges i formler i destinationsarket. Disse følger ikke med. Så har jeg prøvet at foruddefinere områder i destinationsarket (dvs. oprette de 4 ark på fohånd), men da de bliver slettet forsvinder mit navngivne/foruddefinerede område ?
Årsagen til låsning af "kilde" er, hvis koden afbrydes og disse to linier ikke udføres: xls.Quit Set xls = Nothing
Sker det genstart.....
Her er koden, der ikke kopiere - men overføre udfylde celler fra kilde til modtager:
Const stiData = "C:\Documents and Settings\pb\Skrivebord\1803KopierArk_MiRa\data.xls" 'Tilpasses Dim xls As Object Sub kopierData() Dim dataR, dataK Set xls = CreateObject("Excel.Application") With xls .Workbooks.Open stiData .Visible = True dataR = .ActiveCell.SpecialCells(xlLastCell).Row dataK = ActiveCell.SpecialCells(xlLastCell).Column
Rem Overføre alle celler fra "kilden", der er udfyldt i tilsvarende ark/"modtager" For ark = 1 To 4 .ActiveWorkbook.Sheets(ark).Activate For r = 1 To dataR For k = 1 To dataK If .Cells(r, k) <> "" Then ActiveWorkbook.Sheets(ark).Cells(r, k) = .Cells(r, k) End If Next k Next r Next ark End With
Hej Supertekst. Du er en travlt mand. Men jeg holder dig selvfølgelig også rigeligt beskæftiget med alle mine spørgsmål.
Hvornår afbrydes koden ???
Jeg tester lige den anden. Men dvs. at alle 4 ark skal være oprettet i destinationsfilen og så overskrives calalerne bare når jeg aktiverer makroen ? Arkene slettes ikke ?
Overfører den så også callenavngivningen ? Eller bibeholder den dem i destinationarket hvis jeg har navngivet områder der ?
Jeg har nemlig en datavalidering i et 5'te ark i destinationsarket som henter data fra de 4 ark som overføres.
Sub kopierData() Dim Data As Variant, Ark As Integer Application.ScreenUpdating = False Workbooks.Open "C:\Data\data.xls" 'Tilpasses, husk at rette filnavnet i de andre linier også. For Ark = 1 To 4 Workbooks("data.xls").Activate ' husk at rette filnavnet i de andre linier også. Data = ActiveWorkbook.Sheets(Ark).UsedRange ThisWorkbook.Activate Sheets(Ark).Activate Cells.ClearContents Range(Cells(1, 1), Cells(UBound(Data, 1), UBound(Data, 2))) = Data Next Ark Workbooks("data.xls").Close (False) ' husk at rette filnavnet i de andre linier også. Application.ScreenUpdating = True End Sub
Arkene skal være oprettet på forhånd. Du ville have de 4 ark skjuli, ser jeg, det er med her.
Sub kopierData() Dim Data As Variant, Ark As Integer Application.ScreenUpdating = False Workbooks.Open "C:\Data\data.xls" 'Tilpasses, husk at rette filnavnet i de andre linier også. For Ark = 1 To 4 Workbooks("data.xls").Activate ' husk at rette filnavnet i de andre linier også. Data = ActiveWorkbook.Sheets(Ark).UsedRange ThisWorkbook.Activate Sheets(Ark).Activate Cells.ClearContents Range(Cells(1, 1), Cells(UBound(Data, 1), UBound(Data, 2))) = Data Sheets(Ark).Visible = False Next Ark Workbooks("data.xls").Close (False) ' husk at rette filnavnet i de andre linier også. Application.ScreenUpdating = True End Sub
Jeg har delvist fået din makro til at virke. Men jeg kan se på skærmen at den kører alle arkene igennem i destinationsfilen og at den opdaterer dem. Men det sidste den gør er at springe til ark1 og "fjerne" opdateringen igen ????? Således at der altså ikke er ændret noget.
Ok så prøver vi med navnene som du ser på fanerne, ret dem selv til.
Sub kopierData() Dim Data As Variant, ArkNavn As Variant, Ark As Integer ArkNavn = Array("Ark1", "Ark2", "Ark3", "Ark4") ' ret disse navne til at passe med dine arknavne. ' de skal være ens i begge mapper Application.ScreenUpdating = False Workbooks.Open "C:\Data\data.xls" 'Tilpasses, husk at rette filnavnet i de andre linier også. For Ark = 0 To 3 Workbooks("data.xls").Activate ' husk at rette filnavnet i de andre linier også. Data = ActiveWorkbook.Sheets(ArkNavn(Ark)).UsedRange ThisWorkbook.Activate Sheets(ArkNavn(Ark)).Activate Cells.ClearContents Range(Cells(1, 1), Cells(UBound(Data, 1), UBound(Data, 2))) = Data Sheets(ArkNavn(Ark)).Visible = False Next Ark Workbooks("data.xls").Close (False) ' husk at rette filnavnet i de andre linier også. Application.ScreenUpdating = True End Sub
Min fejl var at kalde det forkerte kildeark. Jeg stavede ikke ordentligt.
Den skrivebeskytter (eller siger at "Data.xls er allerede åben"), men kun nogle gange, og jeg har ikke fundet systematikken endnu.
Men lige nu fungerer det fint.
Må man stille et par ekstra spørgsmål (man kan jo aldrig få nok) Jeg åbner også gerne et nyt spørgsmål
1. Kan man lave et lopslag som slår værdien til venstre for søgeværdien op ?
Og noget helt andet:
2. Prøv at se denne løsning (fra Supertekst faktisk). Man kan taste linienummer i funktionen "visaktuellerække" og så viser den værdierne i userformen for den linie i regnearket. Men kan man ændre det så den slå værdierne i kolonne A op og viser dem i userformen:
Const grøn = &HC0FFC0 Const gul = &H80FFFF Dim rækIArk, aktuelleRæk Private Sub f_afslut_Click() ClearFelter Unload UserForm End Sub Private Sub f_clear_Click() ClearFelter aktuelleRæk = rækIArk visAktuelleRække End Sub Private Sub f_gem_Click() Rem test om alle felter er udfyldt If Me.f_medarbnr.Value <> "" And _ Me.f_navn.Value <> "" And _ Me.f_adresse.Value <> "" And _ Me.f_postnr.Value <> "" And _ Me.f_timesats.Value <> "" And _ Me.f_by.Value <> "" Then If Me.f_gem.BackColor = grøn Then OpdaterIArk rækIArk Else OpdaterIArk aktuelleRæk End If Else MsgBox ("Alle felter skal udfyldes") Me.f_medarbnr.SetFocus End If End Sub Private Sub f_visAktuelleRække_Exit(ByVal Cancel As MSForms.ReturnBoolean) If IsNumeric(Me.f_visAktuelleRække.Value) = True And _ Val(Me.f_visAktuelleRække.Value) > 1 And _ Val(Me.f_visAktuelleRække.Value) <= rækIArk Then aktuelleRæk = Val(Me.f_visAktuelleRække) visAktuelleRække End If End Sub
Private Sub SpinButton1_SpinUp() If aktuelleRæk - 1 >= 11 Then aktuelleRæk = aktuelleRæk - 1 End If visAktuelleRække End Sub Private Sub SpinButton1_SpinDown() If aktuelleRæk + 1 <= rækIArk Then aktuelleRæk = aktuelleRæk + 1 End If visAktuelleRække End Sub Private Sub visAktuelleRække() Me.f_visAktuelleRække.Value = aktuelleRæk If aktuelleRæk = rækIArk Then Me.f_visAktuelleRække.BackColor = grøn Me.f_gem.Caption = "Gem" Me.f_gem.Accelerator = "G" Me.f_gem.BackColor = grøn Else Me.f_visAktuelleRække.BackColor = gul Me.f_gem.Caption = "Ret/slet" Me.f_gem.Accelerator = "K" Me.f_gem.BackColor = gul Me.f_sletRækkedata = False End If
Me.f_medarbnr.SetFocus End Sub Private Sub OpdaterIArk(række) If Me.f_sletRækkedata = False Then Cells(række, 1) = Me.f_medarbnr.Value Cells(række, 2) = Me.f_navn.Value Cells(række, 3) = Me.f_adresse.Value Cells(række, 4) = Me.f_postnr.Value Cells(række, 5) = Me.f_by.Value Cells(række, 6) = Me.f_tlf.Value Cells(række, 7) = Me.f_fax.Value Cells(række, 8) = Me.f_timesats.Value Else Rows(CStr(række) + ":" + CStr(række)).Select Selection.Delete Shift:=xlUp End If
rækIArk = findFørsteLedigeRække aktuelleRæk = rækIArk visAktuelleRække Cells(rækIArk, 1).Select ClearFelter End Sub Private Function findFørsteLedigeRække() Dim r For r = 11 To 65000 If Cells(r, 1) = "" Then findFørsteLedigeRække = r Exit Function End If Next r End Function
"2. Prøv at se denne løsning (fra Supertekst faktisk). Man kan taste linienummer i funktionen "visaktuellerække" og så viser den værdierne i userformen for den linie i regnearket. Men kan man ændre det så den slå værdierne i kolonne A op og viser dem i userformen:"
Hvor står det den skal søge efter ?? Hvilket Ark og hvilken kolonne ??
Det første spørgsmål fandt jeg også selv lige ud af på denne måde:
=INDEKS( Varenr; SAMMENLIGN( B19; Materialer; 0))
Spørgsmål 2: Altså hvis jer udfylder userformen og trykker gem så står der fra kolonne A til G: medarbnr, navn, projekt, ugedag, uge, timer
Hvis jeg så står i userformen igen så kan jeg bruge spinbutton til at bladre om og ned i de rækker med data i og hvis der står data på rækken så viser den automatisk de data i userformen så jeg kan rette dem. Jeg kan også bare skrive rækkenummeret i søgefeltet i userformen, så viser den dataene fra den pågældende række.
Men i stedet for at skrive rækkenr. vil jeg hellere skrive medarbnr., altså værdien fra kolonne A. Og hvis det medarbejdernummer findes skal den returner hele rækkens data til userformen.
Det virker som om at efter jeg har "brugt" data-filen, altså hentet data fra den fra en skabelon e.l., så er den efter Excel's termer stadig åben/og dermed skrivebeskyttet i ca. 5-10 minutter.
Man kan dog ikke se at filen er åben.
Efter 5-10 minutter så er den mulig at åbne igen ???
Er det fordi nogle af makroerne skal søge en hulens bunke linier igennem ???
Det er ikke optimalt at man ikke kan bruge data-filen andet end med 5-10 minutters mellemrum.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.