VBA-kod excell 2010

Anonym
2019-04-28T17:03:29+00:00

Hej,

Jag har skapat en mall för protokoll i vilken jag lagt in nåra VBA-finesser i celler för en kolumn. I dessa celler ligger en "Checkbox" (Chb1, Chb2, os.v som öppnar ETT formulär som man sedan kan göra nåra val på och när man sedan klickar "OK" så ska datat från formuläret (UserForm1), ramla in på första lediga (tomma) cell i kolumn A, samt att datat skrivs in i den cell som öppnat upp formuläret, dvs genom villkoret "om Chb1.Value = True, Then. . . cellens värde(text) = formulärets datavärde. Allt detta fungerar perfekt. Detta är skapat på Blad1 i arbetsboken.

Mitt problem blir nu att när jag kopierar bladet och därmed skapar Blad3, så får jag ju givetvis felmeddelande när jag använder "UserForm1" som pekar via kod mot Blad1. . . .?!!!

Min fråga blir således: Hur kan man på ett smart och smidigt sätt anända ETT och SAMMA formulär (UserForm) för flera blad i arbetsboken?

Jag får en känsla av att man måste sätta villkor genom VBA-kod, och använda Activesheet eller nåt sådant. . .

Frustrerad amatör men som älskar att laborera med VBA-koder och dess finesser i excell. :)

// Väl mött. . .

Magnus i Alingsås (072-745 80 40)

Microsoft 365 och Office | Excel | För hemanvändning | Windows

Låst fråga. Den här frågan har migrerats från Microsoft Support Community. Du kan rösta på om det är till hjälp, men du kan inte lägga till kommentarer eller svar eller följa frågan.

0 kommentarer Inga kommentarer

25 svar

Sortera efter: Mest användbara
  1. Anonym
    2019-04-29T14:33:32+00:00

    Då tror jag att jag är med i matchen.

    Vi börjar i andra änden och tar tipsen först, då detta kommer påverka din kod om du väljer att testa det.

    Loopen med att nollställa dina checkboxar handlar om att gå igenom varje checkbox som finns på bladet och sätta värdet till False. Att skriva kod för varje checkbox, speciellt om man har massor, blir många onödiga rader.

    Exempel på kod:

        For Each cb In ws.OLEObjects

            If Left(cb.Name, 3) = "Chb" Then

                cb.Object.Value = False

            End If

        Next cb

    Eftersom jag inte vet om du bara har checkboxar som objekt på bladet måste en koll göras så excel inte försöker sätta andra saker till False. If-satsen kollar att objektet cb har ett namn som börjar på Chb (jag utgår från att alla sina checkboxar heter som du visat tidigare; Chb1, Chb2, Chb3....Chb112)

    Variablerna här är cb (för checkbox) och ws (för worksheet).

    Du bör ha med en deklaration överst i koden för dessa där du skriver

    Dim cb As Object

    Dim ws As Worksheet

    Sen kommer vi till det här med dynamiska blad, alltså vi låser inte in oss på bara Blad1. Direkt efter Dim-satserna i din kod skriver du

    Set ws = Activesheet

    Detta gör att variabeln ws nu kan användas överallt där vi vill skriva/läsa mot det blad som är aktivt, och inte bara mot ett och samma blad.

    Om du lagt till Dim ws As Worksheet överst i koden kan du nu byta ut alla Blad1 mot ws. T ex Blad1.Range(…) blir ws.Range(…), Blad1.Chb1 blir ws.Chb1 … osv.

    När du letar första lediga cell i en kolumn kan man låta excel kolla var denna finns via ett End-kommando. Det finns i princip två vägar här och i mina ögon är att leta nedifrån oftast säkrast. Vad menas med det då? Om vi kollar vad End-kommandot gör så är det enklast att visa genom en tangentbordskombination. Ställ dig överst i en kolumn som har sammanhängande celler med värden i sig. Tryck Ctrl+Pil Ned, vad händer? Du hamnar i den nedersta cellen med värden i den kolumnen. Detta är i princip likvärdigt med koden End(xlDown). Om du ställer dig i samma kolumn i en tom cell ett antal rader nedanför sista cellen med data i och trycker Ctrl+Pil Upp. Du hamnar i den sista cellen med data. Detta är likvärdigt med koden End(xlUp).

    För- och nackdelar med de båda:

    Om du har tomma celler i din kolumn är det alltid bäst att söka nedifrån. Har du bara en rubrik och resten av kolumnen är tom är det bäst att söka nedifrån.

    Har du annan data nedanför den data du söker i är det bäst att söka uppifrån.

    Hursomhelst, jag visar hur du med en kodrad får fram raden för första lediga cell genom att söka nedifrån upp.

    i = ws.cells(rows.Count, 1).end(xlup).offset(1, 0).row

    Eftersom End() pekar ut sista cellen lägger man till Offset(1,0), som betyder förskjutning, och vi förskjuter här med 1 rad och 0 kolumner, annars skriver vi över värdet i den sista cellen. Det är cellen EFTER sista cellen med data vi vill ha.

    Variabeln i kan du nu använda för att skriva i rätt cell i A-kolumnen, typ:

    ws.Range("A" & i) = ….

    Observera att man inte behöver ha

    Range("A" & i).Select

    och sen

    Range("A" & i) = nåt värde

    för att skriva i en cell.

    Du kan direkt skriva Range("W100") = 150 eller liknande för vilka celler som helst utan att du använder Select först.

    Select har man bara om man aktivt vill ställa sig i en viss cell. Att använda Select slöar bara ned koden.

    Du skulle kunna skriva textvärdet från din textbox till cellen i A-kolumnen med en enda rad. (Inga Select, inga loopar)

    ws.cells(rows.Count, 1).end(xlup).offset(1, 0) = Txt1.Text

    Laborera och kolla om du hängde med i allt detta. Tipset är att testa i en kopia av din riktiga fil, ifall det skulle skita sig rejält.

    Minsta motstånd eller fågelholksuttryck, hör av dig.

    Var det här svaret till hjälp?

    0 kommentarer Inga kommentarer
  2. Anonym
    2019-04-29T12:37:58+00:00

    Hej,

    Va bra att du hjälper mig att förenkla om det går och behövs. Jag skriver kod för knappfunktioner såsom jag blivit lärd, och mycket är självlärt utifrån läsning i hjälpmedel, VBA-böcker etc. Jag har bif två bilder på hierarkin och formuläret. (skrolla för att se båda).

    Man väljer först via Spinbuttonknappen ett värde och sedan trycker man på den ljusgrå kommandoknappen. Allt från UserForm1. Formuläret öppnas genom att man bockar i Chb1 i cell Q14, Chb2 i cell Q15 os.v.

    När koden koden körs som står för kommandoknappen så avslutas den med att anropa en allmän "Sub" för att "nollställa" alla checkboxar (Blad1.Chb1.Value = False) i cell Q14 t.o.m Q125(Chb112). Den Sub-rutin funkar ju endast mot Blad1 såsom jag skrivit den nu. . .

    Värdet i textrutan på formuläret skrivs in i den cell som har aktiv checkbox (Value = True) samt i första lediga cell i kolumn A. Jag vill nu att koden ska konstrueras så att den känner av vilket blad jag jobbar ifrån, och styr ner värdet från textrutan på formuläret till rätt blad men samma kolumnval enl ovan. Likaså en loop som "Nollställer checkboxarna" på aktuellt blad. 

    I mitt ex ovan i föreg meddelande, så är det fel angivet med Sub Checkbox (glöm det). Det är koden "Call Checkbox" som gäller och kommer i den ordning som jag visar ovan. Alltså anropet på att nollställa checkboxarna.

    Gällande bladen så är det så att protokollmall görs för olika teknikslag per blad(flik). Geoteknik, BANA_MARK, Signal, Kontaktledning, Kanalisation etc. Jag vill ju ha en färdig mall för ett teknikslag med inbyggda funktioner enl ovan som jag sedan kan koipera så att jag får så många blad som täcker dom antal teknikslag vi jobbar med. Därmed skapas ju Blad 1, Blad 2, Blad 3 osv. OBS! Blad2 har jag avsatt till ett "Datablad" för dataverifiering (förval) till mallen i vissa kolumner.

    Du får visa kodförslag på loop för checkboxarna samt även för hur du menar med kod för att hitta första tomma cell på annat sätt än det jag skrivit det på. Likaså det du nämner om "select" och istället sätta ett värde för cellen utan att välja den - låter i mina ören märkligt just nu, men spännande.  

    ogat 2 bilder som visar hur VBA-hierarkin och formuläret ser ut. ![](https://learn-attachment.microsoft.com/api/attachments/e60aae3f-598f-4fac-adf3-13cd50957cb5?platform=QnA

    Var det här svaret till hjälp?

    0 kommentarer Inga kommentarer
  3. Anonym
    2019-04-29T09:42:09+00:00

    Oj, det finns nog en hel del vi kan ta tag i här.

    Dock är det några frågetecken från min sida, så vi börjar där så vi inte misstolkar varandra.

    -Den första koden triggas när man klickar på en CommandButton, som är placerad på ett UserForm.

    Den andra koden triggas när man klickar på en SpinButton och även den är placerad på ett UserForm.

    Om dina objekt som triggas är på ett UserForm så ska givetvis din kod vara i samma modul som hör till detta UserForm, inte en vanlig Modul jag sa i förra inlägget. Så det verkar ok här, glöm det jag nämnde tidigare om moduler.

    -Jag har inte riktig koll på dina blad. Du hänvisar till Blad1 i koden där dina Checkbox finns, men i den andra koden hänvisar du till Blad2 och nämner att du får problem här när du kopierar till Blad3. Vad är Blad2 för något? Fanns inte allt på Blad1 och du ville kopiera sen till Blad2, Blad3...osv?

    -Den första koddelen verkar märklig. Är det inkopierat fel? Du har Sub CheckBox() mitt inne i Sub Cmd1_Click().

    -I den andra koden, var kommer variabeln i ifrån? Den bara dyker upp. Hur vet man dess värde?

    Övriga tips gällande koden, som inte har något med ditt problem att göra:

    • När det gäller just dina checkbox så är det mycket smidigare att bara loopa igenom alla checkbox och sätta deras värden till False än att uttryckligen skriva alla 112 stycken rad för rad.
    • Du behöver inte loopa dig igenom rad för rad för att hitta första tomma cell. Det finns en kod för detta.
    • När man vill skriva något i en cell behöver man aldrig använda Select först, man anger cellen och sätter dess värde utan att välja den.

    Tipsen kan vi ta när vi fixat ditt huvudsakliga problem.

    Var det här svaret till hjälp?

    0 kommentarer Inga kommentarer
  4. Anonym
    2019-04-28T19:15:59+00:00

    Hej P3excel och stort tack för ditt svar. Det är dock för mig som inte har den erfarenhet och utvecklade kunskapen i VBA-kodning, lite svårt att hänga med i det du bekriver men jag hänger med på det stora taget.

    Förutom det så tack för tipset angående mitt telefonnummer. När jag läste det du skrev så kände jag direkt "hål i huvudet" på mig själv. Rent idiotiskt att lämna ut detta och jag vet faktiskt inte varför. . .

    Åter till min frågeställning;

    Mitt formulär ser ut så här:

    När man rullat fram via Spinbutton-knappen ett värde och sedan trycker på verkställ så har jag skrivit följande kod:

    Private Sub Cmd1_Click()

    x = MsgBox("Har du valt nytt löpnr?", vbYesNo Or vbQuestion, "Kontrollfråga")

    If x = vbYes Then

    Dim i As Integer

    i = 14

    Do Until Blad1.Range("A" & i) = ""

        i = i + 1

        Blad1.Range("A" & i).Select

    Loop

    Blad1.Range("A" & i) = Txt1.Text

           If Blad1.Chb1.Value = True Then

           Blad1.Range("Q14") = Txt1.Text

           ElseIf Blad1.Chb2.Value = True Then

           Blad1.Range("Q15") = Txt1.Text

    Sub Checkbox()

    Blad1.Chb1.Value = False

    Blad1.Chb2.Value = False

    . . . osv ner till Chb112. . .

    End If

        Call Checkbox

    Unload Me

    ElseIf x = vbNo Then

    UserForm1.Txt1.SetFocus

    End If

    OBS! "Call Checkbox" är en allmän Sub som anropas för att återställa samtliga checkboxar på bladet till att bli tomma (Value=False).

    Koden för Spinbuttonknappen på formuläret ser ut så här:

    Private Sub Spn1_SpinDown()

    On Error Resume Next

    If i = 0 Then

    i = 2

    End If

    If i < 51 Then

    Spn1.Value = i

    Spn1.Value = Spn1.Value + 1

    i = Spn1.Value

    Txt1.Text = Blad2.Range("A" & i)

    End If

    End Sub

    Som du ser så står "Bald2" överallt då man jobbar med protokollet (mallen) på blad 2. Om jag nu kopierar och gör fler blad blir det ju "körfel".

    Med att skriva kod i Modul - menar du att jag ska infoga en modul och skriva kod där? Vilken kod ska skrivas där och hur?

    / MGExcel

    Var det här svaret till hjälp?

    0 kommentarer Inga kommentarer
  5. Anonym
    2019-04-28T18:17:31+00:00

    Det är alltid rekommenderat att uttryckligen tala om vilket blad man jobbar mot när man skyfflar data till/från celler i de olika blad man har. Även om det inte alltid ger Körfel så finns risken att saker blir fel utan att man vet om det.

    Har man bara ett blad, visst då kan man komma undan med det, men det är lika bra att sätta en god programmeringsvana så slipper man framtida frustrationer för den sakens skull.

    Det finns ytterligare en sak, vilket inte framkommer i din text, och det är var du placerat din kod - dvs i vilken typ av modul. Om du generellt ska låta kod fungera över flera blad bör koden finnas i en modul och inte i en bladrelaterad sektion. Dvs ramen i det fönster där koden finns bör heta Modul1(kod) eller liknande, och inte Blad1(kod).

    Ok, tillbaka till din kod för aktiva blad.

    Det du kan göra är att deklarera en variabel som sätts till det blad som är aktivt.

    Dim ws As Worksheet

    Set ws = Activesheet

    ws kommer nu alltid peka på (eller vara satt till) det aktiva bladet, oavsett vilket blad som du jobbar i.

    När celler ska skrivas i eller hämtas data ifrån så anger man alltid detta tillsammans med Cells eller Range eller vad man nu väljer att anropa cellområden med. T ex, ws.Cells(1, 1) eller ws.Range("A1") betyder A1 i det blad som satts.

    ws i detta fall kallas (på engelska) för en qualifier, och den talar om så att säga var man håller till. Jag brukar likna detta vid när man säger åt en taxichaufför var man ska. Säger du bara Storgatan 1 så åker taxin till den adressen i den stad du är i - vad annars. Men säger du Villevalla.Storgatan1 så har du med qualifiern sagt att det är i annan stad (annat blad på excelspråk). Detta är en bra sed att anamma när man jobbar i Excel-vba.

    Men, ovanstående ska normalt inte ge problem (även om man bör ha koll på i vilket blad man bollar i), eftersom det aktiva bladet per automatik är just det som syns när du kör, men kan ge fel om man jobbar över flera blad.

    Du säger att du får fel eftersom UserForm1 pekar mot Blad1 via kod....hur? vad har du för kod som gör detta? Utan att se vad du gör är det svårt att peka på vad du borde göra istället.

    Din fråga "Hur kan man på ett smart och smidigt sätt använda ETT och SAMMA formulär (UserForm) för flera blad i arbetsboken?"

    Svaret är, du SKA bara använda ett formulär. Allt annat vore dumdristigt och slöseri med tid att koda för flera blad. Och vägen dit är via icke hårdkodade referenser för de blad du har, vilket som nämndes jag skulle vilja se hur du gör.

    Ett annat tips.

    Lägg inte ut personliga uppgifter i allmänna forum och liknande, som ditt telenr.

    Var det här svaret till hjälp?

    0 kommentarer Inga kommentarer