Avatar billede pollo Nybegynder
18. maj 2009 - 10:49 Der er 8 kommentarer og
1 løsning

afrunding

Hej jeg har en db hvor jeg for en kunde skal afregne pr påbegyndt ½ time . Jeg har lavet  2 felter med tid og udregner så i et felt i forespørgelsen forskellen mellem de 2 tidspunkter. I et andet felt  omsætter jeg denne værdig til decimaltal. Da kunden ønsker helt præcise tidspunkter og ikke f.eks.  11.00 til  11.30 men 11.00 til 11.17 er jeg nød til at lave en OPrundning  Hvordan definerer jeg en OPrunding  således at  f.eks  17 minutter blive en halv time og  31 minutter 1 time ?? Mvh Knud
Avatar billede fennec Nybegynder
18. maj 2009 - 12:59 #1
Lad mig starte med at sige jeg ikke ved hvordan det gøres i Access, men siden du endnu ikke har fået en kommentar, tænke jeg at jeg måske kunne hjælpe dig på vej...

Det du skal have fat i er modulus. Det er en funktion som dividere 2 tal og returnere resten. Programmeringsmæssig hedder den normalt Mod eller % (afhængig af sprog).

Eks:
rest = 7 mod 30
rest = 37 mod 30
eller
rest = 7 % 30
rest = 37 % 30

rest er så lig 7 i begge tilfælde. Det kan du så bruge i din beregning, så det bliver noget ala:
minutter = 37
oprundet = minutter + (30- (minutter mod 30))

Eneste problem der er at hvis minutter = 30 så er resten 0 og der bliver lagt 30 min til så oprundet=60, men det burde kunne klares med en if betingelse.

if (minutter mod 30)
  oprundet = minutter
else
  oprundet = minutter + (30- (minutter mod 30))

Håber det kan hjælpe dig på rette vej...
Avatar billede Slettet bruger
18. maj 2009 - 14:26 #2
Function timeDifRoundUp(d0tfirst, d0tlast, minutLeastUnit As Integer)
    timeDifRoundUp = d0tlast - d0tfirst
    If d0tfirst > d0tlast Then timeDifRoundUp = timeDifRoundUp + 1
    timeDifRoundUp = Int(24 * 60 * timeDifRoundUp)
    If timeDifRoundUp Mod minutLeastUnit > 0 Then
        timeDifRoundUp = (Int(timeDifRoundUp / minutLeastUnit) + 1) * minutLeastUnit: End If
    timeDifRoundUp = timeDifRoundUp / 60 / 24
End Function

?cdate(timeDifRoundUp(cdate("11:00"),cdate("14:01"),30))

03:30:00

?cdate(timeDifRoundUp(cdate("21:00"),cdate("3:10"),30))

06:30:00
Avatar billede pollo Nybegynder
18. maj 2009 - 16:09 #3
Hej  brugerekspert. Ser meget rigtigt ud  men jeg behøver lige en forklaring på hvor jeg skal lægge denne kode. Jeg ville have gået ind i forespørgelsen og oprettet et felt med formel af en eller anden slags men det er vel ikke det du vil ?? Jeg går også ud fra at d0tlast og d0tfirst = mine felter for slut og start. Eller er jeg helt forkert på den. ?  Mvh Knud
Avatar billede Slettet bruger
18. maj 2009 - 16:23 #4
Funktionen lægges i et standard modul, og refereres til i forespørgslen.
Avatar billede pollo Nybegynder
18. maj 2009 - 17:22 #5
hej igen - det er helt fint med korte kontante svar  men det er ikke helt nok til mig. Har jeg ret i at d0tlast og d0tfirst = mine felter for slut og start. Hvis ja - hvad dækker udtrykket  minutLeastUnit  over. ?  Når jeg lægger mine feltnavne i koden beder den  minutLeastUnit
Avatar billede Slettet bruger
18. maj 2009 - 20:26 #6
Hej Knud
Jeg troede ellers, jeg havde brugt sigende navne - men måske ikke ;) Access har ikke en klokkeslet felttype, men en tidspunkt felttype - derfor prefixet 'd0' for at indikere at der arbejdes på Date typen - rigtigt gættet first=start, last=slut - måske lidt en smagssag.

Jeg undrede mig først lidt over at du selv havde glemt hvilken 3 parameter du efterspurgte i det oprindelige spørgsmål - men klart, du har nok ikke tænkt på den halve time, som noget 'der skulle kunne skrues på'.
- det gør man så, når man programmerer - finder den mest generelle essens - funktionsnavn og parametre skal også læses som et hele - havde den være hardcoded til 30 minutter, havde jeg kaldt den
'timeDifRoundUp30m(...'

Du kan anføre den som 30, lave variablen i parameterdeklarationen om til 'optional minutLeastUnit As Integer=30', eller skrive funktionen om (gøres ved at fjerne minutLeastUnit fra parameterdeklarationen og erstatte dens forekomster med 30 i funktionskroppen.)
--
Benny
Avatar billede pollo Nybegynder
18. maj 2009 - 21:23 #7
Hej Benny  - tak for svaret  fint og uddybend men jeg må indrømme at jeg ikke kan følge med - eller sagt på en anden måde evnerne på dette område slår ikke til. Jeg bliver nok nød til at overveje en anden løsning. -tak for hjælpen - send et svar så jeg kan give nogle point mvh knud
Avatar billede Slettet bruger
19. maj 2009 - 17:36 #8
Jeg skal ikke have nogen point - gem du dem bare til en anden gang, jeg skriver slet ikke for pointgenes skyld.
Måske har jeg ikke det store 'hjælpegen' - har 1000'vis at timer med ms-access bag mig, og er mere interesset i principper.
Avatar billede pollo Nybegynder
22. juni 2009 - 13:07 #9
Hej igen..
Nu har jeg fået lidt hjælp til at få din kode til at fungere, men vi er stødt på et sjovt problem..

Hvis jeg laver en test på koden som du har gjort #2 kommentar med:
?cdate(timeDifRoundUp(cdate("11:00"),cdate("14:01"),30))
03:30:00
så fungere det hele fint, men så snart jeg indsætter mine felter i stedet for de faste tidspunkter, så fungere den som følgende:

[LevAfg] = 11:00 og [LevAnk] = 14:01
?cdate(timeDifRoundUp(cdate([LevAfg]),cdate([LevAnk]),30))
03:00:00

og hvis jeg ændrer [LevAnk] = 14.02, så:
?cdate(timeDifRoundUp(cdate([LevAfg]),cdate([LevAnk]),30))
03:30:00

Jeg kan ikke helt forstå hvad der går galt, men et eller andet siger mig at det er mine felter som forårsager fejlen, men helt præcis hvad det skulle være ved jeg ikke..

Mvh.
Knud
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Dyk ned i databasernes verden på et af vores praksisnære Access-kurser

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester