VBA - Mismatch de tip (Eroare 13 în timpul rulării)

Ce este o eroare de nepotrivire de tip?

O eroare de nepotrivire poate apărea adesea atunci când rulați codul VBA. Eroarea va opri codul dvs. să ruleze complet și va fi semnalizat prin intermediul unei casete de mesaj pe care această eroare trebuie să o rezolve

Rețineți că, dacă nu v-ați testat complet codul înainte de a fi distribuit utilizatorilor, acest mesaj de eroare va fi vizibil pentru utilizatori și va cauza o mare pierdere de încredere în aplicația dvs. Excel. Din păcate, utilizatorii fac adesea lucruri foarte specifice unei aplicații și sunt deseori lucruri pe care tu, ca dezvoltator, nu le-ai luat în considerare niciodată.

O eroare de nepotrivire de tip apare deoarece ați definit o variabilă folosind instrucțiunea Dim ca un anumit tip, de ex. întreg, dată și codul dvs. încearcă să atribuie o valoare variabilei care nu este acceptabilă, de ex. șir de text atribuit unei variabile întregi ca în acest exemplu:

Iată un exemplu:

Faceți clic pe Depanare și linia de cod contravenientă va fi evidențiată în galben. Nu există nicio opțiune în fereastra pop-up de eroare pentru a continua, deoarece aceasta este o eroare majoră și nu există nicio modalitate în care codul poate rula mai departe.

În acest caz particular, soluția este de a schimba instrucțiunea Dim într-un tip de variabilă care funcționează cu valoarea pe care o atribuiți variabilei. Codul va funcționa dacă schimbați tipul variabilei în „Șir” și probabil că ați dori să schimbați și numele variabilei.

Cu toate acestea, schimbarea tipului de variabilă va necesita resetarea proiectului dvs. și va trebui să rulați din nou codul chiar de la început, ceea ce poate fi foarte enervant dacă este implicată o procedură lungă

Eroare de nepotrivire cauzată de calculul foii de lucru

Exemplul de mai sus este unul foarte simplu al modului în care poate fi produsă o eroare de nepotrivire și, în acest caz, este ușor de remediat

Cu toate acestea, cauza erorilor de nepotrivire este de obicei mult mai profundă și nu este atât de evidentă atunci când încercați să depanați codul.

De exemplu, să presupunem că ați scris cod pentru a prelua o valoare într-o anumită poziție pe o foaie de lucru și că conține un calcul dependent de alte celule din registrul de lucru (B1 în acest exemplu)

Foaia de lucru arată ca acest exemplu, cu o formulă pentru a găsi un anumit caracter într-un șir de text

Din punctul de vedere al utilizatorului, celula A1 este în format liber și poate introduce orice valoare dorește. Cu toate acestea, formula caută o apariție a caracterului „B” și, în acest caz, nu este găsită, astfel încât celula B1 are o valoare de eroare.

Codul de test de mai jos va produce o eroare de nepotrivire, deoarece a fost introdusă o valoare greșită în celula A1

1234 Sub TestMismatch ()Reduceți numărul meu ca întregMyNumber = Foi ("Sheet1"). Interval ("B1"). ValoareSfârșitul Sub

Valoarea din celula B1 a produs o eroare deoarece utilizatorul a introdus un text în celula A1 care nu este conform cu ceea ce era așteptat și nu conține caracterul „B”

Codul încearcă să atribuie valoarea variabilei „Numărul meu”, care a fost definită pentru a aștepta un număr întreg, astfel încât să primiți o eroare de nepotrivire.

Acesta este unul dintre aceste exemple în care verificarea meticuloasă a codului dvs. nu va oferi răspunsul. De asemenea, trebuie să căutați pe foaia de lucru de unde provine valoarea pentru a afla de ce se întâmplă acest lucru.

Problema este de fapt pe foaia de lucru, iar formula din B1 trebuie modificată, astfel încât valorile de eroare să fie tratate. Puteți face acest lucru folosind formula „IFERROR” pentru a furniza o valoare implicită 0 dacă caracterul de căutare nu este găsit

Apoi puteți încorpora cod pentru a verifica o valoare zero și pentru a afișa utilizatorului un mesaj de avertizare că valoarea din celula A1 este nevalidă

12345678 Sub TestMismatch ()Reduceți numărul meu ca întregMyNumber = Foi ("Sheet1"). Range ("B1"). TextDacă MyNumber = 0 AtunciMsgBox „Valoarea la celula A1 este nevalidă”, vbCriticalIeșiți din SubEnd IfSfârșitul Sub

De asemenea, puteți utiliza validarea datelor (grupul de instrumente de date din fila Date a panglicii) de pe foaia de calcul pentru a opri utilizatorul să facă tot ce le-a plăcut și să provoace în primul rând erori în foaia de lucru. Permiteți-le să introducă doar valori care nu vor provoca erori în foaia de lucru.

Puteți scrie codul VBA pe baza evenimentului Change din foaia de lucru pentru a verifica ce a fost introdus.

De asemenea, blocarea și parola protejează foaia de lucru, astfel încât datele nevalide să nu poată fi introduse

Eroare de nepotrivire cauzată de valorile de celulă introduse

Erorile de nepotrivire pot fi cauzate în codul dvs. prin introducerea valorilor normale dintr-o foaie de lucru (non-eroare), dar în cazul în care utilizatorul a introdus o valoare neașteptată, de ex. o valoare text când așteptați un număr. Este posibil să fi decis să introducă un rând într-un interval de numere, astfel încât să poată pune o notă într-o celulă explicând ceva despre număr. La urma urmei, utilizatorul nu are nicio idee despre modul în care funcționează codul dvs. și că tocmai a aruncat totul din bucată, introducând nota sa.

Exemplul de cod de mai jos creează o matrice simplă numită „Numărul meu” definit cu valori întregi

Codul iterează apoi printr-o gamă de celule de la A1 la A7, atribuind valorile celulei în matrice, utilizând o variabilă „Coun” pentru indexarea fiecărei valori

Când codul atinge valoarea textului, o eroare de nepotrivire este cauzată de aceasta și totul se oprește

Dând clic pe „Depanare” în fereastra pop-up de eroare, veți vedea linia de cod care are problema evidențiată în galben. Plasând cursorul peste orice instanță a variabilei „Coun” din cod, veți putea vedea valoarea „Coun” în cazul în care codul a eșuat, care în acest caz este 5

Privind pe foaia de lucru, veți vedea că 5a celula în jos are valoarea textului și acest lucru a cauzat eșecul codului

Puteți schimba codul introducând o condiție care verifică mai întâi o valoare numerică înainte de a adăuga valoarea celulei în matrice

12345678910111213 Sub TestMismatch ()Dim MyNumber (10) As Integer, Coun As IntegerCoun = 1DoDacă Coun = 11, apoi ieșiți din DoDacă IsNumeric (Foi ("sheet1"). Celule (Coun, 1). Valoare) AtunciMyNumber (Coun) = Foi ("sheet1"). Celule (Coun, 1). ValoareAltfelMyNumber (Coun) = 0End IfCoun = Coun + 1BuclăSfârșitul Sub

Codul folosește funcția „IsNumeric” pentru a testa dacă valoarea este de fapt un număr, iar dacă este, atunci îl introduce în matrice. Dacă nu este număr, atunci introduce valoarea zero.

Acest lucru asigură faptul că indicele matrice este menținut în linie cu numerele rândurilor de celule din foaia de calcul.

De asemenea, ați putea adăuga cod care copiază valoarea erorii originale și detaliile locației într-o foaie de lucru „Erori”, astfel încât utilizatorul să poată vedea ce au greșit când rulează codul dvs.

Testul numeric folosește codul complet pentru celulă, precum și codul pentru a atribui valoarea în matrice. Ați putea susține că acest lucru ar trebui atribuit unei variabile pentru a nu repeta același cod, dar problema este că ar trebui să definiți variabila ca o „variantă”, ceea ce nu este cel mai bun lucru de făcut.

De asemenea, aveți nevoie de validarea datelor pe foaia de lucru și pentru a proteja parola cu foaia de lucru. Acest lucru va împiedica utilizatorul să introducă rânduri și să introducă date neașteptate.

Eroare de nepotrivire cauzată de apelarea unei funcții sau subrutine folosind parametri

Când se apelează o funcție, de obicei treceți parametrii funcției utilizând tipuri de date deja definite de funcție. Funcția poate fi una deja definită în VBA sau poate fi o funcție definită de utilizator pe care ați creat-o singur. O rutină secundară poate necesita uneori parametri

Dacă nu respectați convențiile privind modul în care parametrii sunt transferați la funcție, veți primi o eroare de nepotrivire

12345678 Funcția de apelare secundară ()Dim Ret As IntegerRet = Funcția mea (3, „test”)Sfârșitul SubFuncția MyFunction (N Ca întreg, T Ca Șir) Ca ȘirMyFunction = TFuncția de sfârșit

Există mai multe posibilități aici pentru a obține o eroare de nepotrivire

Variabila returnată (Ret) este definită ca un număr întreg, dar funcția returnează un șir. De îndată ce rulați codul, acesta va eșua deoarece funcția returnează un șir, iar acesta nu poate intra într-o variabilă întreagă. Interesant este că rularea Debug pe acest cod nu detectează această eroare.

Dacă puneți ghilimele în jurul primului parametru care este trecut (3), acesta este interpretat ca un șir, care nu se potrivește cu definiția primului parametru din funcție (întreg)

Dacă faceți al doilea parametru din apelul funcțional într-o valoare numerică, acesta va eșua cu o nepotrivire, deoarece al doilea parametru din șir este definit ca un șir (text)

Eroare de nepotrivire cauzată de utilizarea funcțiilor de conversie în VBA incorect

Există o serie de funcții de conversie pe care le puteți utiliza în VBA pentru a converti valori în diferite tipuri de date. Un exemplu este „CInt” care convertește un șir care conține un număr într-o valoare întreagă.

Dacă șirul de convertit conține caractere alfa, atunci veți primi o eroare de nepotrivire, chiar dacă prima parte a șirului conține caractere numerice, iar restul sunt caractere alfa, de ex. „123abc”

Prevenirea generală a erorilor de nepotrivire

Am văzut în exemplele de mai sus mai multe moduri de a face față unor erori potențiale de nepotrivire în cadrul codului dvs., dar există o serie de alte moduri, deși acestea nu pot fi cele mai bune opțiuni:

Definiți variabilele dvs. ca tip de variantă

Un tip de variantă este tipul de variabilă implicit în VBA. Dacă nu utilizați o instrucțiune Dim pentru o variabilă și pur și simplu începeți să o utilizați în codul dvs., atunci i se dă automat tipul de Variantă.

O variabilă Variant va accepta orice tip de date, indiferent dacă este un număr întreg, întreg lung, număr cu precizie dublă, valoare booleană sau text. Sună ca o idee minunată și vă întrebați de ce toată lumea nu își setează toate variabilele la variantă.

Cu toate acestea, varianta tipului de date are mai multe dezavantaje. În primul rând, ocupă mult mai multă memorie decât alte tipuri de date. Dacă definiți o matrice foarte mare ca variantă, aceasta va înghiți o cantitate imensă de memorie atunci când rulează codul VBA și ar putea cauza cu ușurință probleme de performanță

În al doilea rând, are o performanță mai lentă, în general, decât dacă utilizați anumite tipuri de date. De exemplu, dacă efectuați calcule complexe folosind numere cu virgulă plutitoare, calculele vor fi considerabil mai lente dacă stocați numerele ca variante, mai degrabă decât numere cu precizie dublă

Utilizarea tipului de variantă este considerată programare neglijentă, cu excepția cazului în care există o necesitate absolută pentru aceasta.

Utilizați comanda OnError pentru a gestiona erorile

Comanda OnError poate fi inclusă în codul dvs. pentru a face față blocării erorilor, astfel încât, dacă apare vreodată o eroare, utilizatorul vede un mesaj semnificativ în loc de fereastra pop-up standard de eroare VBA

1234567 Sub ErrorTrap ()Reduceți numărul meu ca întregOn Error GoTo Err_HandlerMyNumber = "test"Err_Handler:MsgBox „Eroarea” & Err.Description & „a apărut”Sfârșitul Sub

Acest lucru împiedică efectiv eroarea să oprească buna funcționare a codului și permite utilizatorului să se recupereze curat din situația de eroare.

Rutina Err_Handler ar putea afișa informații suplimentare despre eroare și pe cine să contacteze în legătură cu aceasta.

Din punct de vedere al programării, atunci când utilizați o rutină de gestionare a erorilor, este destul de dificil să localizați linia de cod pe care este activată eroarea. Dacă parcurgeți codul folosind F8, de îndată ce linia de cod ofensatoare este rulată, acesta trece la rutina de gestionare a erorilor și nu puteți verifica unde merge greșit.

O modalitate de a rezolva acest lucru este să configurați o constantă globală care este adevărată sau falsă (booleană) și să o utilizați pentru a activa sau dezactiva rutina de gestionare a erorilor utilizând o instrucțiune „Dacă”. Când doriți să testați eroarea, tot ce trebuie să faceți este să setați constanta globală la False, iar gestionarul de erori nu va mai funcționa.

1 Global Const ErrHandling = False
1234567 Sub ErrorTrap ()Reduceți numărul meu ca întregDacă ErrHandling = Adevărat, atunci la eroare GoTo Err_HandlerMyNumber = "test"Err_Handler:MsgBox „Eroarea” & Err.Description & „a apărut”Sfârșitul Sub

Singura problemă cu acest lucru este că permite utilizatorului să se recupereze după eroare, dar restul codului din subrutină nu se execută, ceea ce poate avea repercusiuni enorme mai târziu în aplicație

Folosind exemplul anterior de looping printr-o gamă de celule, codul ar ajunge la celula A5 și ar atinge eroarea nepotrivită. Utilizatorul va vedea o casetă de mesaje care oferă informații despre eroare, dar nimic din celula respectivă nu va fi procesat.

Utilizați comanda OnError pentru a elimina erorile

Aceasta folosește comanda „On Error Resume Next”. Acest lucru este foarte periculos să îl includeți în codul dvs., deoarece împiedică afișarea oricăror erori ulterioare. Aceasta înseamnă practic că, pe măsură ce codul dvs. se execută, dacă apare o eroare într-o linie de cod, execuția se va muta la următoarea linie disponibilă fără a executa linia de eroare și va continua ca în mod normal.

Acest lucru poate rezolva o posibilă situație de eroare, dar va afecta în continuare fiecare eroare viitoare din cod. S-ar putea să credeți că codul dvs. nu conține erori, dar de fapt nu este și părți din codul dvs. nu fac ceea ce credeți că ar trebui să facă.

Există situații în care este necesară utilizarea acestei comenzi, cum ar fi dacă ștergeți un fișier folosind comanda „Kill” (dacă fișierul nu este prezent, va exista o eroare), dar captarea erorilor ar trebui întotdeauna comutată înapoi imediat după locul în care ar putea apărea eroarea potențială folosind:

1 La Eroare Goto 0

În exemplul anterior de looping printr-o gamă de celule, folosind „On Error Resume Next”, aceasta ar permite buclei să continue, dar celula care cauzează eroarea nu va fi transferată în matrice și elementul matricei pentru acel index particular ar deține o valoare nulă.

Conversia datelor într-un tip de date pentru a se potrivi cu declarația

Puteți utiliza funcțiile VBA pentru a modifica tipul de date al datelor primite, astfel încât să se potrivească cu tipul de date al variabilei de recepție.

Puteți face acest lucru când treceți parametrii la funcții. De exemplu, dacă aveți un număr care este ținut într-o variabilă șir și doriți să îl transmiteți ca număr unei funcții, puteți utiliza CInt

Există o serie de funcții de conversie care pot fi utilizate, dar aici sunt cele principale:

CInt - convertește un șir care are o valoare numerică (sub + sau - 32.768) într-o valoare întreagă. Rețineți că acest lucru trunchiază orice punct zecimal

CLng - Convertește un șir care are o valoare numerică mare într-un întreg lung. Punctele zecimale sunt tăiate.

CDbl - Convertește un șir care deține un număr cu virgulă plutitoare într-un număr dublu de precizie. Include puncte zecimale

CDate - Convertește un șir care deține o dată într-o variabilă de dată. Depinde parțial de setările din Panoul de control Windows și de localizarea dvs. de modul în care este interpretată data

CStr - Convertește o valoare numerică sau de dată într-un șir

La conversia dintr-un șir într-un număr sau o dată, șirul nu trebuie să conțină nimic altceva decât numerele sau o dată. Dacă sunt prezente caractere alfa, aceasta va produce o eroare de nepotrivire. Iată un exemplu care va produce o eroare de nepotrivire:

123 Subtest ()MsgBox CInt ("123abc")Sfârșitul Sub

Testarea variabilelor în cadrul codului dvs.

Puteți testa o variabilă pentru a afla ce tip de date este înainte de a o atribui unei variabile de un anumit tip.

De exemplu, puteți verifica un șir pentru a vedea dacă este numeric utilizând funcția „IsNumeric” din VBA

1 MsgBox IsNumeric ("123test")

Acest cod va returna False deoarece, deși șirul începe cu caractere numerice, conține și text, astfel încât nu reușește testul.

1 MsgBox IsNumeric („123”)

Acest cod va reveni True deoarece este vorba de caractere numerice

Există o serie de funcții în VBA pentru a testa diferite tipuri de date, dar acestea sunt principalele:

IsNumeric - testează dacă o expresie este sau nu un număr

IsDate - testează dacă o expresie este sau nu o dată

IsNull - testează dacă o expresie este nulă sau nu. O valoare nulă poate fi introdusă doar într-un obiect variantă, altfel veți primi o eroare „Utilizarea nevalidă a valorii nule”. O casetă de mesaj returnează o valoare nulă dacă o utilizați pentru a pune o întrebare, astfel încât variabila returnată trebuie să fie o variantă. Rețineți că orice calcul care utilizează o valoare nulă va returna întotdeauna rezultatul valorii nule.

IsArray - testează dacă expresia reprezintă sau nu o matrice

IsEmpty - testează dacă expresia este goală sau nu. Rețineți că golul nu este același cu nul. O variabilă este goală atunci când este definită pentru prima dată, dar nu este o valoare nulă

În mod surprinzător, nu există nicio funcție pentru IsText sau IsString, ceea ce ar fi cu adevărat util

Obiecte și erori de nepotrivire

Dacă utilizați obiecte, cum ar fi un interval sau o foaie, veți primi o eroare de nepotrivire la momentul compilării, nu la timpul de rulare, ceea ce vă va avertiza că codul dvs. nu va funcționa

123456 Sub TestRange ()Dim MyRange As Range, I As LongSetați MyRange = Range („A1: A2”)I = 10x = UseMyRange (I)Sfârșitul Sub
12 Funcția UseMyRange (R As Range)Funcția de sfârșit

Acest cod are o funcție numită „UseMyRange” și un parametru transmis ca obiect de interval. Cu toate acestea, parametrul transmis este un număr întreg lung care nu se potrivește cu tipul de date.

Când rulați codul VBA, acesta este compilat imediat și veți vedea acest mesaj de eroare:

Parametrul ofensator va fi evidențiat cu un fundal albastru

În general, dacă faceți greșeli în codul VBA folosind obiecte, veți vedea acest mesaj de eroare, mai degrabă decât un mesaj de nepotrivire de tip:

Vei ajuta la dezvoltarea site-ului, partajarea pagina cu prietenii

wave wave wave wave wave