Gå til innhold

Finnes det data i Excel-arket ?


Anbefalte innlegg

Hei. Siden det er lettere å lære VB her enn på Google, prøver jeg på denne :)

Følgende kode looper gjennom worksheets i aktiv Excel arbeidsbok, og rekalkulerer alle celler med lysegul bakgrunn. Har dog et problem med at om den møter et tom ark (ws) kommer det en feilmelding om at den "ikke finner noen celler", og debugger går til linje 2 i denne koden...

 

Finnes det en sjekk som kan flytte meg til "next ws" om ws.UsedRange ikke inneholder noen celler ? Noe ala "if ws.UsedRange = 0 Then Next ws"

 

For Each ws In wb.Worksheets
   For Each cell In ws.UsedRange.SpecialCells(xlCellTypeConstants, 1)
       If cell.Value <> 0 And cell.Interior.ColorIndex = 19 _
       Then cell.Value = cell.Value / kurs
   Next cell
Next ws

Lenke til kommentar
Videoannonse
Annonse

Først, endre koden din til følgende:

For Each ws In wb.Worksheets

    For Each cell In GetSpecialCells(ws.UsedRange)

        If cell.Value <> 0 And cell.Interior.ColorIndex = 19 Then

            cell.Value = cell.Value / kurs

        End If

    Next

Next

Legg så til denne prosedyren i en tilgjengelig modul (helst den samme):

Private Function GetSpecialCells(Range As Range) As Object

 

    ' Hopper over alle linjer som invokerer en feilmelding

    On Error Resume Next

 

    ' Ved å sette returverdien FØR den usikre koden kjører, kan vi

    ' forsikre oss at vi alltid vil returnere et objekt. Collection

    ' brukes bare ettersom den støtter IEnumVARIANT.

    Set GetSpecialCells = New Collection

    Set GetSpecialCells = Range.SpecialCells(xlCellTypeConstants, 1)

 

End Function

Lenke til kommentar

Hei igjen

 

Dette er litt tuklete, men veldig nyttig. Det du gjør er å tilordne alle tallceller til en variabel mens du tillater at koden feiler en liten stund. Så sjekker du om variabelen inneholder noe i det hele tatt, hvilket den ikke gjør der tallceller ikke finnes.

 

Sub test()

 

Dim wb As Workbook

Dim ws As Worksheet

Dim MyRange As Range

Dim cell As Range

Set wb = ActiveWorkbook

For Each ws In wb.Worksheets

On Error Resume Next

Set MyRange = Nothing

Set MyRange = ws.UsedRange.SpecialCells(xlCellTypeConstants, 1)

On Error GoTo 0

If Not MyRange Is Nothing Then

For Each cell In MyRange

'If cell.Value <> 0 And cell.Interior.ColorIndex = 19 _

'Then cell.Value = cell.Value / kurs

Next cell

Else

'MsgBox "Ingenting i " & ws.Name

End If

Next ws

 

End Sub

 

Jeg vet det tar litt tid å venne seg til en logikk a la

If Not MyRange Is Nothing Then

men så... :)

 

HTH. Beste hilsen Harald

Endret av Harald Staff
Lenke til kommentar

Takker begge to. Jeg skal nok prøve å forstå det etterhvert, men akkurat nå tok jeg en klipp og lim, og det funket som en kule. VB er mer gøy enn man skulle tro.

Kode :

Klikk for å se/fjerne innholdet nedenfor
Option Explicit

Private Sub UserForm_Initialize()

 

'Setter standardverier i input-skjemaet

txtKurs.Value = "1,0000"

With cboValg

.AddItem "Svensk"

.AddItem "Norsk"

End With

cboValg.Value = "Svensk"

txtKurs.SetFocus

 

End Sub

Private Sub cmdAvslutt_click()

Unload Me

End Sub

Private Sub cmdKonverter_click()

 

Dim ws As Worksheet, wb As Workbook, cell As Range

Dim valg As String, kurs As Double

Set wb = ActiveWorkbook

Set ws = ActiveSheet

kurs = Me.txtKurs.Value

valg = Me.cboValg.Value

 

'Om startbeløpene er svenske dividerer vi alle gule celler med kursen

Select Case valg

Case "Svensk"

For Each ws In wb.Worksheets

For Each cell In GetSpecialCells(ws.UsedRange)

If cell.Value <> 0 And cell.Interior.ColorIndex = 19 Then

cell.Value = cell.Value / kurs

End If

Next

Next

Me.cboValg = "Norsk"

 

'Om startbeløpene er norske multipliserer vi dem med kursen

Case "Norsk"

For Each ws In wb.Worksheets

For Each cell In GetSpecialCells(ws.UsedRange)

If cell.Value <> 0 And cell.Interior.ColorIndex = 19 Then

cell.Value = cell.Value * kurs

End If

Next

Next

Me.cboValg = "Svensk"

 

'Just in case...

Case Else

MsgBox "Gyldig kurs - ikke funnet"

End Select

 

End Sub

Private Function GetSpecialCells(Range As Range) As Object

 

' Hopper over alle linjer som invokerer en feilmelding

On Error Resume Next

 

' Ved å sette returverdien FØR den usikre koden kjører, kan vi

' forsikre oss at vi alltid vil returnere et objekt. Collection

' brukes bare ettersom den støtter IEnumVARIANT.

Set GetSpecialCells = New Collection

Set GetSpecialCells = Range.SpecialCells(xlCellTypeConstants, 1)

 

End Function

post-3875-1174662919_thumb.png

Lenke til kommentar

For ikke å ødelegge den vakre posten hiver jeg inn en dobbel her.

Harald: Ser du benytter "On Error Resume Next" der jeg prøvde "if ws.UsedRange = 0 Then Next ws" (Miljøskadet da jeg lærer php parallelt)

Vil "On Error" kunne overkjøre alle feil i en For-Each loop, og slik benyttes som sikkerhet i alle løkker som ikke skal reagere på exeptions (.. en slags "best practice" i VB) ?

Lenke til kommentar
Vil "On Error" kunne overkjøre alle feil i en For-Each loop, og slik benyttes som sikkerhet i alle løkker som ikke skal reagere på exeptions (.. en slags "best practice" i VB) ?

8220335[/snapback]

Problemet med On Error Resume Next er at den fører til at programmet hopper over linjen der en feil inntreffer, ikke blokken den definerer. La meg illustrere dette med et eksempel. La oss si en funksjon Bar alltid invokerer en feil. I følgende kode vil kodelinje Item.DoAction (som da vil referere til Foo) kjørt, selv om en muligens skulle tro programmet hopper over hele FOR EACH-kodeblokken:

On Error Resume Next

Dim Item As Object

 

Set Item = Foo

 

For Each Item In Bar

    Item.DoAction

Next

Endret av aadnk
Lenke til kommentar

Jeg er ikke sikker på at jeg skjønner spørsmålet helt. On Error Resume Next gjør at programmet tillater feil -feil både som at jeg programmerer elendig og som at programmet bes å utføre meningsløse absurditeter. I det virkelige liv, hvor man ikke alltid kan forutse enhver tenkelig situasjon, utgjør resume next gjerne forskjellen mellom å gjøre dårlig arbeid eller å krasje. Noen ganger er det ene å foretrekke, andre ganger det andre. Ja, du kan sette On Error resume Next og så kode nærmest hvasomhelst. Du får et tregt og dårlig program, men krasje, det gjør det i hvert fall ikke.

 

I kontrollerte forhold ber du programmet om å gjøre det umulige, og så sjekker du hvordan det gikk. Dermed vet du om påfunnet er umulig eller ikke, f.eks. i betydningen "hent alle tall i et miljø helt uten tall". Kommandoen On Error GoTo 0 nullstiller denne liberalistiske holdningen til påfunn -det krasjer altså ved senere feil.

 

HTH. Beste hilsen Harald

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...