Expressie dat datum uit een nummercombinatie kan onttrekken.

Status
Niet open voor verdere reacties.

muufley

Gebruiker
Lid geworden
23 sep 2010
Berichten
47
Hallo, ik heb een database dat de stock beheert van voedselproducten. Elk product heeft een lotnummer dat de datum weergeeft. Een voorbeeld is 10/392 waarbij de 10 staat voor het jaar 2010, 39 is het weeknummer en 2 is de dag van de week. Dit is dan de datum van vandaag namelijk 2/10/2010. Voor de reële lotdatum moet ik dan nogmaals 1 dag bijtellen wat uitkomt op 3/10/2010.
Voorlopig vul ik de lotdatum nog manueel in, is het mogelijk om een expressie te maken dat mij automatisch deze datum geeft gebaseerd op het lotnummer zonder dat ik deze telkens moet invullen?
 
Je zou een reguliere expressie kunnen gebruiken. Erg ingewikkeld, maar zoiets als dit moet kunnen lukken.

Je zou dan eerst de 10, 39 en 2 moeten scheiden, en dan nog even moeten rekenen met de dag en maand...

Daniel
 
Je zou een reguliere expressie kunnen gebruiken. Erg ingewikkeld, maar zoiets als dit moet kunnen lukken.

Je zou dan eerst de 10, 39 en 2 moeten scheiden, en dan nog even moeten rekenen met de dag en maand...

Daniel

Ja dat kan iedereen bedenken.
Heb je ook een oplossing?

Tardis
 
Ik weet niet of het iets uitmaakt maar het lotnummer veld is een textveld, niet nummeriek.
 
Nee dat maakt niks uit... Maar hoe moet ik deze code lezen: 10/114?
Is dat 4-11-2010 of 14-1-2010?
Lijkt mij wel wat uit te maken...
 
Dan wil ik toch wel eerst weten hoe de 14e van week 1 er uit ziet...
 
Octafish ik snap niet goed wat je vraagt. Een jaar telt 52 weken waarvan week 1 begint op de eerste maandag van het jaar. Voor 2010 is dit maandag 4 januari, 14de dag van week 1 bestaat niet aangezien een week maar 7 dagen telt.
Bijvoorbeeld 14 januari is een donderdag (4de dag van week 2) dat is dan 10/024. De indeling is eigenlijk gewoon "jaar/week,dag v/d week".
 
Was inderdaad een beetje in de war zullen we maar zeggen ;) De datumconstructie is ook een beetje afwijkend. Als ik het goed begrijp, is je laatste getal dus >1 en <8, en kan het getal ervoor 1 of 2 cijfers hebben.
Het terugrekenen is op zich niet zo moeilijk. Met de functie Weekday() bereken je het dagnummer uit een datum, en voor het weeknummer zijn verschillende functies te vinden. Dat is wel afhankelijk van de rekenmethode, want je kunt het weeknummer op verschillende manieren berekenen. Met daaruit dus verschillende datums... Maar laten we even uitgaan van een functie die het ISO weeknummer berekent, dan is je werkwjze als volgt:
Eerst lees je de jaarwaarde in, en daar maak je een jaartal van. Simpel genoeg lijkt mij, hoef ik niet uit te leggen.
Vervolgens loop je door alle dagen van het jaar. De datum die overreenkomt met het weeknummer en dagnummer, is de juiste.
 
Het is een afwijkende constructie. Het is inderdaad zo dat het laatste getal >1 en <8 is, het getal ervoor is altijd twee cijfers.
Ik heb zo het gevoel dat om dit te ontleden redelijk ingewikkeld is. Vooral die weeknummers maken het alles behalve makkelijk, vandaar mijn vraag.
 
Ik heb 'm anders al opgelost...
De eerste twee functies berekenen een weeknummer op basis van een datum.
Code:
Public Function WeekNum(ZoekDatum As Date, Optional WhichFormat As Variant) As Integer
'Versie laatst bijgewerkt: 2-4-2008
Dim PreviousYearStart As Date, ThisYearStart As Date, NextYearStart As Date
Dim ThisYear As Integer, YearNum As Integer, iYearStart As Date
ThisYear = Year(ZoekDatum)
ThisYearStart = YearStart(ThisYear)
PreviousYearStart = YearStart(ThisYear - 1)
NextYearStart = YearStart(ThisYear + 1)
Select Case ZoekDatum
    Case Is >= NextYearStart
        WeekNum = (ZoekDatum - NextYearStart) \ 7 + 1
        YearNum = Year(ZoekDatum) + 1
    Case Is < ThisYearStart
        WeekNum = (ZoekDatum - PreviousYearStart) \ 7 + 1
        YearNum = Year(ZoekDatum) - 1
    Case Else
        WeekNum = (ZoekDatum - ThisYearStart) \ 7 + 1
        YearNum = Year(ZoekDatum)
End Select
If IsMissing(WhichFormat) Then
    Exit Function
End If
If WhichFormat = 2 Then
    WeekNum = CInt(Format(Right(YearNum, 2), "00") & Format(WeekNum, "00"))
End If
End Function
Code:
Private Function YearStart(WhichYear As Integer) As Date
'Versie laatst bijgewerkt: 2-4-2008
Dim WeekDay As Integer, NewYear As Date
    NewYear = DateSerial(WhichYear, 1, 1)
    WeekDay = (NewYear - 2) Mod 7
    If WeekDay < 4 Then
        YearStart = NewYear - WeekDay
    Else
        YearStart = NewYear - WeekDay + 7
    End If
End Function
De volgende code berekent de feitelijke datum.
Code:
Function DatumTerug(DatumTekst As String) As Date
Dim sDatum As String, sTemp() As String
Dim iDag As Integer, iWeek As Integer, iJaar As Integer, i As Integer
Dim iStart As Date, iEind As Date, iDatum As Date
sDatum = DatumTekst
sTemp = Split(sDatum, "/")
iDag = Right(sTemp(1), 1)
iWeek = Left(sTemp(1), Len(sTemp(1)) - 1)
If sTemp(0) > Right(Year(Date), 2) Then
    iJaar = 1900 + sTemp(0)
Else
    iJaar = 2000 + sTemp(0)
End If
iStart = DateSerial(iJaar, 1, 1)
iEind = DateSerial(iJaar + 1, 1, 1)
Do While iStart < iEind
    If WeekNum(iStart) = iWeek Then
        Do While WeekDay(iStart, vbMonday) < iDag
            iStart = iStart + 1
        Loop
        Exit Do
    End If
    iStart = iStart + 1
Loop
DatumTerug = iStart
End Function
Op een formulier kun je e.e.a. uittesten met een opdrachtknop:
Code:
Private Sub Knop31_Click()
Dim sTekst As String
sTekst = InputBox("Typ een datumcode", "Datum conversie")
MsgBox DatumTerug(sTekst)
End Sub
 
Bedankt voor de moeite octafish maar hoe kan ik deze vba code toepassen in een formulier of query. Ik heb nog nooit met vba gewerkt in access 2007. Ik zie dat hiermee oa Yearnum en weeknum modules gemaakt worden maar verder kom ik niet. Mijn bedoeling is dat bij het invullen van het lotnummer de datum automatisch in een andere kolom van mijn query verschijnt.
 
In query zou je kunnen gebruiken:

Code:
LotDatum: DateAdd("d"; CInt(Right$(LotNummer; 1)) - Weekday(DateSerial(CInt(Left$(LotNummer; 2)); 1; 1); vbMonday); DateAdd("ww"; CInt(Mid$(LotNummer; 4; 2)); DateSerial(CInt(Left$(LotNummer; 2)); 1; 1)))

Wel uitproberen of deze formule altijd goed werkt!!
Formule lijkt indrukwekkender dan ie is.
In het kort:
Je berekent de datum op basis van weeknummer en 1 januari, en telt daar dan weer dagen bij op basis van de dag, gecorrigeerd met dagen dat week 1 niet op 1/1 hoeft te beginnen.

Jaar is DateSerial(CInt(Left$(LotNummer; 2))
Week is CInt(Mid$(LotNummer; 4; 2))
Dag is CInt(Right$(LotNummer; 1))
 
Laatst bewerkt door een moderator:
Harry, jou expressie werkt. Als ik in de query die code ingeef vraagt access mij de parameter value voor vbmonday. Als ik de waarde 3 ingeef krijg ik exact de datum die ik wens. Als ik ze vergelijk met mijn manuele waardes zijn deze hetzelfde. Maar dit is echter enkel zo voor het jaar 2010. Ik heb ook nog lotnummers van 2008 en 2009 en bij deze wijken de dagen af. Ook met een test voor het jaar 2011 is dit het geval. Ik ga ervan uit dat de vbmonday parameter waarde enkel geldt voor het jaar 2010. Is er mogelijkheid om die parameter waarde ook in te stellen voor andere jaren?
 
De waarde voor vbMonday is 2, die moet je dus gebruiken.
Als je een dag later wilt zien dan het LotNummer eigenlijk aangeeft, moet je dat corrigeren met:
Code:
DateAdd("d"; CInt(Right$(LotNummer; 1)) - Weekday(DateSerial(CInt(Left$(LotNummer; 2)); 1; 1); 2) + 1...

Met de verschillende jaren is al wel rekening gehouden. Probleem is dat weeknummer in Access niet altijd juist is. Het kan dus zijn dat je voor andere jaren extra moet corrigeren!
Je kunt dat ondervangen door een functie te schrijven en die te gebruiken in je query.
 
Laatst bewerkt door een moderator:
De code die ik heb gepost is ook vrij simpel te gebruiken: plak alle code in een Module, en gebruik hem als volgt in een query:
De variant met dateAdd is overigens op dezelfde manier ook simpel in een functie onder te brengen, zodat je in queries niet van die ingewikkelde constructies hoeft te maken elke keer als je een datum wilt genereren.

Lotdatum:Datumterug("Lotnummer")
 
Laatst bewerkt:
Het spijt me Octafish maar ik geraak er niet aan uit met jouw oplossing :confused:. Ik zou niet weten wat ik met die modules moet aanvangen. Ik denk dat ik zal blijven bij Harry's oplossing die bij nader inzicht toch lijkt te werken voor dit jaar en de jaren 2011 en 2012. Het eigenaardige is dat het met 7dagen teveel scheelt voor 2008 en 2009 maar dat de datums dan weer kloppen voor 2006 en 2007.
Harry ik zou ook niet weten wat voor functie ik moet schrijven, ik gebruik access nog maar voor 6 weken, alles is nog nieuw. Misschien dat het mij later wel lukt maar ik stel mij voorlopig tevreden en zal er dan gewoon rekening mee moeten houden dat voor de jaren 2008 en 2009 een week teveel geteld wordt.
In ieder geval bedankt voor jullie assistentie.

Nog een klein vraagje. Moest in het lotnummer voorbeeld 10/009 de laatste 3 cijfers staan voor de dag van het jaar (9 januari 2010) (of 10/032 = 1 februari 2010) hoe zou een dergelijke expressie er dan uitzien in een query om tot een datum te komen?
 
Om mijn oplossing te gebruiken, die overigens de juiste weken teruggeeft, moet je een Module maken. Als je 2007 kan ik je zo uit het hoofd niet helpen, maar het maakt niet uit hoe je die module noemt. Daar plak je alle code in uit mijn eerdere post. Het gebruik ervan in een query is dan zoals ik in mijn vorige post heb uitgelegd. Volgens mij kun je in 2007 vrij makkelijk een nieuwe module maken; is niet afgeschermd voor zover ik weet.
Wat betreft het laatste deel van je vraag: als je het getal gebruikt als de zoveelste dag in het jaar, dan kun je met DateAdd makkelijk een datum berekenen:
Code:
LotDatum: DateAdd("d"; CInt(Mid(Lotnummer; InStr(1; Lotnummer; "/") + 1; Len(Lotnummer) - InStr(1; Lotnummer; "/"))); DateSerial(2000 + CInt(Left(Lotnummer; 2)); 1; 1)) - 1
Als je dat handig vindt, kan ik wel ee voorbeeldje posten met de functie er in. Kun je zien hoe het werkt...
 
Als je wil ja, ik zit al de hele dag te zoeken uren aan een stuk en ik kom er maar niet uit. Harry's oplossing lijkt achteraf gezien ook niet zo interessant omdat bij elke beweging telkens die parameter waarde gevraagd wordt. Misschien kan ik met een voorbeeldje eens ontleden hoe zoiets in elkaar steekt.
 
Zal even een voorbeeldje maken van de code.
 
Status
Niet open voor verdere reacties.

Nieuwste berichten

Terug
Bovenaan Onderaan