Hvorfor
Ja hvorfor skrive en artikel om hvordan man tæller tegn i en streng?
Mere fordi jeg har lyst til at vise hvor nemt det gøres og hvordan man bedst skriver kode der er let at læse. Jeg har tit ærgret mig over hvordan nogen skriver uden at formatere med korrekt indrykning samt uden kort beskrivelse.
I dette tilfælde kopierer du følgende kode ind i et nyt modul:
Option Explicit
Public Function TextCount(ByVal Text As String, ByVal SearchString As String,
Optional CaseSense As Boolean = True) As Long
On Error GoTo errTrap
' Tjekker om der overhovedet er noget tekst
If Len(Text) > 0 And Len(SearchString) > 0 Then
If CaseSense Then
' Tegnene skal være i samme Case (Store / Små bogstaver)
TextCount = UBound(Split(Text, SearchString))
Else
' Kig ikke efter tegnenes Case (Store / Små bogstaver)
TextCount = UBound(Split(LCase(Text), LCase(SearchString)))
End If
Else
TextCount = 0
End If
Exit Function
errTrap:
' Der opstod en fejl som der ikke er taget højde for
TextCount = -1
' Beskeden kan med fordel udelades, da vi returnerer -1
MsgBox "En fejl opstod i funktionen TextCount." & vbLf & _
"Fejlbesked: " & Err.Description, vbExclamation
End Function
Læg først mærke til at der sørges for at pakke funktionen ind i en simpel men stærk errorhandler, hvis der opstår en fejl (hvad der ikke skulle kunne ske) vil funktionen returnere et -1 til koden hvorfra funktionen er kaldt.
Den første egentlige kode tjekker for om der overhovedet er overført noget tekst og søgestreng, hvis en af dem mangler er det ikke nødvendigt at gøre mere end at returnere 0.
Hvis forudsætningerne er ok, så er vi klar til at tælle hvor mange gange at SearchString forekommer i teksten.
Hvordan
Hvordan kan en linie som 'UBound(Split(Text, SearchString))' returnere antal forekomster?
Funktionen Split danner en array som er splittet hver gang at søgestrengen forkommer, det vil sige at hvis du har en tekst der hedder "Maler mester Madsen maler mange malerier" og din søgestreng er lig med "m" så vil der blive dannet en array med følgende indhold:
Array(0) = "Maler "
Array(1) = "ester Madsen "
Array(2) = "aler "
Array(3) = "ange "
Array(4) = "alerier"
Men hvorfor lave en array når man bare vil kende forefomsten af "m", kunne man ikke lave en loop der gennemløb teksten og talte hvor mange forekomster der er?
Jo selvfølgelig kunne man det, men det er bedre at bruge de indbyggede funktioner i VB så meget som muligt, da de er væsentlig hurtigere, faktisk lavede jeg en test hvor jeg henholdsvis lavede funktionen med en loop og med split komandoen, og den sidste var omkr. 10 gange hurtigere.
Men kig nu på det foregående eksempel igen, læg mærke til at teksten ikke er delt ved de store M'er, for i code sprog er "m" og "M" ikke ens, derfor kan du vælge at lægge en lCase() omkring både teksten og søgestrengen, så alle store bogstaver bliver konverteret til små tegn, og du vil få dette resultat:
Array(0) = ""
Array(1) = "aler "
Array(2) = "ester
Array(3) = "adsen "
Array(4) = "aler "
Array(5) = "ange "
Array(6) = "alerier"
Nu mangler vi bare at hente top index værdien af den Array vi har lavet, det gøres hurtigt med UBound(), og koden er faktisk færdig.
Jeg håber at denne artikel kan give lidt ideer omkring formatering af kode, samt en enkel og hurtig opbygning af god kode.