VBA - Type Mismatch (Run -time Error 13)

Hva er en feil som ikke samsvarer med typen?

En feilmelding kan ofte oppstå når du kjører VBA -koden. Feilen vil stoppe koden din fra å kjøre fullstendig og flagge opp ved hjelp av en meldingsboks som denne feilen må sorteres ut

Vær oppmerksom på at hvis du ikke har testet koden din fullt ut før distribusjon til brukere, vil denne feilmeldingen være synlig for brukerne og føre til et stort tap av tillit til Excel -applikasjonen din. Dessverre gjør brukerne ofte veldig særegne ting med en applikasjon og er ofte ting du som utvikler aldri vurderte.

Det oppstår en feil med feil i typen fordi du har definert en variabel ved bruk av Dim -setningen som en bestemt type, f.eks. heltall, dato og koden din prøver å tilordne en verdi til variabelen som ikke er akseptabel, f.eks. tekststreng tilordnet en heltallsvariabel som i dette eksemplet:

Her er et eksempel:

Klikk på Debug og den krenkende linjen med kode vil bli markert med gult. Det er ikke noe alternativ på popup-vinduet for feil å fortsette, siden dette er en stor feil og det er ingen måte at koden kan kjøre videre.

I dette spesielle tilfellet er løsningen å endre Dim -setningen til en variabeltype som fungerer med verdien du tilordner variabelen. Koden vil fungere hvis du endrer variabeltypen til ‘String’, og du vil sannsynligvis også endre variabelnavnet.

For å endre variabeltypen må du imidlertid tilbakestille prosjektet, og du må kjøre koden igjen fra begynnelsen av igjen, noe som kan være veldig irriterende hvis en lang prosedyre er involvert

Uoverensstemmelse feil forårsaket av regnearkberegning

Eksemplet ovenfor er en veldig enkel måte for hvordan en feilmatchingsfeil kan oppstå, og i dette tilfellet kan den lett utbedres

Imidlertid er årsaken til mismatch -feil vanligvis langt dypere enn dette, og er ikke så åpenbar når du prøver å feilsøke koden din.

Anta som et eksempel at du har skrevet kode for å hente en verdi i en bestemt posisjon i et regneark, og den inneholder en beregningsavhengig andre celler i arbeidsboken (B1 i dette eksemplet)

Regnearket ser ut som dette eksemplet, med en formel for å finne et bestemt tegn i en tekststreng

Fra brukerens synspunkt er celle A1 fritt format, og de kan angi hvilken som helst verdi de vil. Formelen leter imidlertid etter en forekomst av tegnet 'B', og i dette tilfellet blir den ikke funnet, så celle B1 har en feilverdi.

Testkoden nedenfor gir en feilmelding fordi feil verdi er angitt i celle A1

1234 Sub TestMismatch ()Dim MyNumber Som HeltallMyNumber = Ark ("Ark1"). Område ("B1"). VerdiSlutt Sub

Verdien i celle B1 har produsert en feil fordi brukeren har lagt inn tekst i celle A1 som ikke samsvarer med det som var forventet, og den inneholder ikke tegnet ‘B’

Koden prøver å tilordne verdien til variabelen 'MyNumber' som er definert for å forvente et helt tall, og så får du en feilmelding.

Dette er et av disse eksemplene der nøye kontroll av koden din ikke vil gi svaret. Du må også se på regnearket hvor verdien kommer fra for å finne ut hvorfor dette skjer.

Problemet er faktisk på regnearket, og formelen i B1 må endres slik at feilverdier behandles. Du kan gjøre dette ved å bruke "IFERROR" -formelen for å gi en standardverdi på 0 hvis søketegnet ikke blir funnet

Du kan deretter inkludere kode for å se etter en nullverdi, og for å vise en advarsel til brukeren om at verdien i celle A1 er ugyldig

12345678 Sub TestMismatch ()Dim MyNumber Som HeltallMyNumber = Ark ("Ark1"). Område ("B1"). TekstHvis MyNumber = 0 DaMsgBox "Verdi i celle A1 er ugyldig", vbCriticalAvslutt SubSlutt omSlutt Sub

Du kan også bruke datavalidering (gruppen Dataverktøy på fanen Data på båndet) på regnearket for å stoppe brukeren med å gjøre hva de liker og forårsake feil i regnearket i utgangspunktet. Bare la dem skrive inn verdier som ikke forårsaker feil i regnearket.

Du kan skrive VBA -kode basert på Endre -hendelsen i regnearket for å kontrollere hva som er lagt inn.

Lås og passordbeskytt også regnearket, slik at ugyldige data ikke kan legges inn

Uoverensstemmelse feil forårsaket av angitte celleverdier

Uoverensstemmelsesfeil kan skyldes koden din ved å hente inn normale verdier fra et regneark (ikke-feil), men der brukeren har angitt en uventet verdi f.eks. en tekstverdi når du ventet et tall. De kan ha bestemt seg for å sette inn en rad innenfor et tallområde, slik at de kan sette en lapp i en celle som forklarer noe om tallet. Tross alt har brukeren ingen anelse om hvordan koden din fungerer, og at de nettopp har kastet det hele ut av kilter ved å skrive inn notatet.

Eksempelkoden nedenfor lager en enkel matrise kalt 'MyNumber' definert med heltallsverdier

Koden gjentar seg deretter gjennom et område av cellene fra A1 til A7, og tildeler celleverdiene i matrisen ved å bruke en variabel 'Coun' for å indeksere hver verdi

Når koden når tekstverdien, forårsakes en feilmelding av dette, og alt stopper

Ved å klikke på 'Debug' i feilmeldingen, vil du se kodelinjen som har problemet markert med gult. Ved å holde markøren over en forekomst av variabelen "Coun" i koden, vil du kunne se verdien av "Coun" der koden mislyktes, som i dette tilfellet er 5

Når du ser på regnearket, vil du se at 5th cell down har tekstverdien, og dette har forårsaket at koden mislyktes

Du kan endre koden din ved å sette inn en tilstand som sjekker etter en numerisk verdi først før du legger til celleverdien i matrisen

12345678910111213 Sub TestMismatch ()Dim MyNumber (10) As Integer, Coun As IntegerTelle = 1GjøreHvis Coun = 11, avslutt DoIf IsNumeric (Sheets ("sheet1"). Cells (Coun, 1) .Value) ThenMyNumber (Coun) = Sheets ("sheet1"). Celler (Coun, 1) .ValueEllersMyNumber (Coun) = 0Slutt omCoun = Coun + 1LøkkeSlutt Sub

Koden bruker "IsNumeric" -funksjonen for å teste om verdien faktisk er et tall, og hvis den er det, legger den den inn i matrisen. Hvis det ikke er tall, angir det verdien på null.

Dette sikrer at matrisindeksen holdes på linje med cellelinjenumrene i regnearket.

Du kan også legge til kode som kopierer den opprinnelige feilverdien og posisjonsdetaljene til et "Feil" -ark, slik at brukeren kan se hva de har gjort feil når koden din kjøres.

Den numeriske testen bruker hele koden for cellen så vel som koden for å tildele verdien til matrisen. Du kan argumentere for at denne bør tilordnes en variabel for ikke å gjenta den samme koden, men problemet er at du må definere variabelen som en ‘variant’, noe som ikke er det beste å gjøre.

Du trenger også datavalidering på regnearket og for å passordbeskytte regnearket. Dette forhindrer brukeren i å sette inn rader og legge inn uventede data.

Uoverensstemmelsesfeil forårsaket av å kalle en funksjon eller en underrutine ved hjelp av parametere

Når en funksjon kalles, sender du vanligvis parametere til funksjonen ved hjelp av datatyper som allerede er definert av funksjonen. Funksjonen kan være en som allerede er definert i VBA, eller det kan være en brukerdefinert funksjon som du har bygd selv. Noen ganger kan en underrutine også kreve parametere

Hvis du ikke holder deg til konvensjonene for hvordan parameterne overføres til funksjonen, får du en feilmelding

12345678 Sub CallFunction ()Dim Ret As IntegerRet = MyFunction (3, "test")Slutt SubFunksjon MyFunction (N Som Heltall, T Som String) Som StringMyFunction = TSluttfunksjon

Det er flere muligheter her for å få en feilmelding

Returvariabelen (Ret) er definert som et heltall, men funksjonen returnerer en streng. Så snart du kjører koden, vil den mislykkes fordi funksjonen returnerer en streng, og denne ikke kan gå inn i en heltallsvariabel. Interessant, ikke kjører Debug på denne koden ikke opp denne feilen.

Hvis du setter anførselstegn rundt den første parameteren som passeres (3), tolkes den som en streng, som ikke samsvarer med definisjonen av den første parameteren i funksjonen (heltall)

Hvis du gjør den andre parameteren i funksjonsanropet til en numerisk verdi, mislykkes det med feil samsvar fordi den andre parameteren i strengen er definert som en streng (tekst)

Uoverensstemmelse feil forårsaket av å bruke konverteringsfunksjoner i VBA feil

Det er en rekke konverteringsfunksjoner du kan bruke i VBA for å konvertere verdier til forskjellige datatyper. Et eksempel er 'CInt' som konverterer en streng som inneholder et tall til en heltallsverdi.

Hvis strengen som skal konverteres inneholder noen alfa -tegn, får du en feilmelding, selv om den første delen av strengen inneholder numeriske tegn og resten er alfa -tegn f.eks. '123abc'

Generell forebygging av feilfeil

Vi har sett i eksemplene ovenfor flere måter å håndtere potensielle mismatch -feil i koden din, men det er en rekke andre måter, selv om de kanskje ikke er de beste alternativene:

Definer variablene dine som Variant Type

En varianttype er standard variabeltype i VBA. Hvis du ikke bruker en Dim -setning for en variabel og bare begynner å bruke den i koden din, får den automatisk typen Variant.

En variantvariabel godtar alle typer data, enten det er et heltall, langt heltall, dobbelt presisjonsnummer, boolsk eller tekstverdi. Dette høres ut som en fantastisk idé, og du lurer på hvorfor alle ikke bare setter alle variablene sine til variant.

Variantdatatypen har imidlertid flere ulemper. For det første tar den opp mye mer minne enn andre datatyper. Hvis du definerer et veldig stort utvalg som variant, vil det svelge en enorm mengde minne når VBA -koden kjører, og kan lett forårsake ytelsesproblemer

For det andre er ytelsen generelt tregere enn hvis du bruker spesifikke datatyper. For eksempel, hvis du foretar komplekse beregninger ved hjelp av flytende desimaltall, vil beregningene bli betydelig tregere hvis du lagrer tallene som varianter, i stedet for doble presisjonsnummer

Å bruke varianttypen regnes som slurvet programmering, med mindre det er absolutt nødvendig for det.

Bruk OnError -kommandoen til å håndtere feil

OnError-kommandoen kan inkluderes i koden din for å håndtere feilfanging, slik at hvis en feil oppstår, ser brukeren en meningsfull melding i stedet for standard VBA-feil

1234567 Sub ErrorTrap ()Dim MyNumber Som HeltallVed feil GoTo Err_HandlerMyNumber = "test"Err_Handler:MsgBox "Feilen" og Err.Description & "har skjedd"Slutt Sub

Dette forhindrer effektivt at feilen stopper problemfri kjøring av koden og lar brukeren komme seg rent fra feilsituasjonen.

Err_Handler -rutinen kan vise ytterligere informasjon om feilen og hvem du kan kontakte om den.

Fra et programmeringssynspunkt er det ganske vanskelig å finne kodelinjen feilen er på når du bruker en rutine for håndtering av feil. Hvis du går gjennom koden ved å bruke F8, så snart den krenkende linjen er kjørt, hopper den til feilhåndteringsrutinen, og du kan ikke kontrollere hvor den går galt.

En måte å unngå dette på er å sette opp en global konstant som er sann eller usann (boolsk) og bruke denne til å slå rutinen for feilhåndtering på eller av ved hjelp av en 'Hvis' -uttalelse. Alt du trenger å gjøre er å sette den globale konstanten til Falsk når du vil teste feilen, og feilbehandleren vil ikke lenger fungere.

1 Global Const ErrHandling = Falsk
1234567 Sub ErrorTrap ()Dim MyNumber Som HeltallHvis ErrHandling = True Then On Error Gå til Err_HandlerMyNumber = "test"Err_Handler:MsgBox "Feilen" og Err.Description & "har skjedd"Slutt Sub

Det eneste problemet med dette er at det lar brukeren komme seg etter feilen, men resten av koden i delrutinen kjøres ikke, noe som kan ha enorme konsekvenser senere i applikasjonen

Ved å bruke det tidligere eksemplet på sløyfe gjennom et utvalg av celler, ville koden komme til celle A5 og treffe feilmeldingen. Brukeren vil se en meldingsboks som gir informasjon om feilen, men ingenting fra den cellen og fremover i området vil bli behandlet.

Bruk OnError -kommandoen for å undertrykke feil

Denne bruker kommandoen 'On Error Resume Next'. Dette er veldig farlig å inkludere i koden din, da det forhindrer at eventuelle senere feil vises. Dette betyr i utgangspunktet at når en kode kjøres, hvis en feil oppstår i en kodelinje, vil utførelsen bare gå til neste tilgjengelige linje uten å utføre feillinjen og fortsette som normalt.

Dette kan sortere ut en potensiell feilsituasjon, men det vil fortsatt påvirke alle fremtidige feil i koden. Du kan da tro at koden din er feilfri, men faktisk er den ikke det, og deler av koden din gjør ikke det du synes den burde gjøre.

Det er situasjoner der det er nødvendig å bruke denne kommandoen, for eksempel hvis du sletter en fil ved hjelp av 'Kill' -kommandoen (hvis filen ikke er tilstede, vil det være en feil), men feilfangingen bør alltid byttes tilbake umiddelbart etter der den potensielle feilen kan oppstå ved å bruke:

1 Ved feil Gå til 0

I det tidligere eksemplet på looping gjennom en rekke celler, ved bruk av 'On Error Resume Next', vil dette gjøre det mulig for sløyfen å fortsette, men cellen som forårsaker feilen vil ikke bli overført til matrisen, og array -elementet for den aktuelle indeksen vil ha en nullverdi.

Konvertering av data til en datatype for å matche erklæringen

Du kan bruke VBA -funksjoner til å endre datatypen for innkommende data slik at den samsvarer med datatypen til den mottakende variabelen.

Du kan gjøre dette når du sender parametere til funksjoner. For eksempel, hvis du har et tall som er inneholdt i en strengvariabel og du vil sende det som et tall til en funksjon, kan du bruke CInt

Det er en rekke av disse konverteringsfunksjonene som kan brukes, men her er de viktigste:

CInt - konverterer en streng som har en numerisk verdi (under + eller - 32 768) til en heltallsverdi. Vær oppmerksom på at dette avkorter eventuelle desimaltegn

CLng - Konverterer en streng som har en stor numerisk verdi til et langt heltall. Desimalpunkt er avkortet.

CDbl - Konverterer en streng som holder et flytende desimaltegn til et dobbelt presisjonsnummer. Inkluderer desimaltegn

CDate - Konverterer en streng som holder en dato til en datovariabel. Avhenger delvis av innstillingene i Windows Kontrollpanel og lokaliteten din på hvordan datoen tolkes

CStr - Konverterer en numerisk eller datoverdi til en streng

Når du konverterer fra en streng til et tall eller en dato, må strengen ikke inneholde noe annet enn tall eller en dato. Hvis det finnes alfa -tegn, vil dette føre til en feilmelding. Her er et eksempel som vil gi en feilmelding:

123 Sub Test ()MsgBox CInt ("123abc")Slutt Sub

Test av variabler i koden din

Du kan teste en variabel for å finne ut hvilken datatype det er før du tilordner den til en variabel av en bestemt type.

For eksempel kan du sjekke en streng for å se om den er numerisk ved å bruke "IsNumeric" -funksjonen i VBA

1 MsgBox IsNumeric ("123test")

Denne koden vil returnere False fordi selv om strengen begynner med numeriske tegn, inneholder den også tekst, så den mislykkes i testen.

1 MsgBox IsNumeric ("123")

Denne koden returnerer True fordi den er alle numeriske tegn

Det er en rekke funksjoner i VBA for å teste for forskjellige datatyper, men disse er de viktigste:

IsNumeric - tester om et uttrykk er et tall eller ikke

IsDate - tester om et uttrykk er en dato eller ikke

IsNull - tester om et uttrykk er null eller ikke. En nullverdi kan bare settes inn i et variantobjekt, ellers får du en feilmelding "Ugyldig bruk av null". En meldingsboks returnerer en nullverdi hvis du bruker den til å stille et spørsmål, så returvariabelen må være en variant. Husk at enhver beregning som bruker en nullverdi alltid vil returnere resultatet av null.

IsArray - tester om uttrykket representerer en matrise eller ikke

IsEmpty - tester om uttrykket er tomt eller ikke. Vær oppmerksom på at tomt ikke er det samme som null. En variabel er tom når den først defineres, men den er ikke en nullverdi

Overraskende nok er det ingen funksjon for IsText eller IsString, noe som ville være veldig nyttig

Objekter og feilfeil

Hvis du bruker objekter som et område eller et ark, vil du få en feilmelding ved kompileringstidspunktet, ikke ved kjøretid, noe som gir deg en behørig advarsel om at koden din ikke kommer til å fungere

123456 Sub TestRange ()Dim MyRange As Range, I As LongAngi MyRange = Range ("A1: A2")Jeg = 10x = UseMyRange (I)Slutt Sub
12 Funksjon BrukMyRange (R som område)Sluttfunksjon

Denne koden har en funksjon som kalles 'UseMyRange' og en parameter som overføres som et områdeobjekt. Parameteren som overføres er imidlertid et langt heltall som ikke samsvarer med datatypen.

Når du kjører VBA -kode, blir den umiddelbart kompilert, og du vil se denne feilmeldingen:

Den krenkende parameteren vil bli markert med en blå bakgrunn

Vanligvis, hvis du gjør feil i VBA -kode ved hjelp av objekter, vil du se denne feilmeldingen, i stedet for en melding om feil samsvar:

Du vil bidra til utvikling av området, dele siden med vennene dine

wave wave wave wave wave