webForumDet fria alternativet

Kalendern vill inte börja med första dagen i månden

ASP

86 svar · 1 703 visningar · startad av plelkes · sida 2 av 5

Frågan, av plelkes

Hej, jag har snickrat ihop en kalender som skall i HTML-tabell visa aktuell månads dagar. Nedanstående kod fungerade perfekt för maj-03 <%@LANGUAGE=VBSCRIPT %> <% Option Explicit %> <HTML> <BODY> <% Session.LCID = 1053 'Vi skapar en array med 42 element. 1:a elementet = 1:a cellen = 1:a Måndagen i månaden '2:a elementet = 2:a cellen = 1:a Tisdagen i månaden 'osv 'Om vi placerar månadens daga

Läs frågan i sin helhet →
Medlem sedan juni 200032 967 inlägg
#21

Jag blir alldeles suddig i huvudet när jag tittar på koden, den känns onödigt kladdig för en gammal räv som jag.

Jag känner mig nödgad att fråga; är det just denna kalender du vill ha, eller går det bra med en annan (som fungerar ;) )?

Jag tror det går snabbare att skriva ihop en ny än att få denna att funka. Nästan. ;)

Mvh

Medlem sedan mars 2002823 inlägg
#22

@nders,
jag har följt rådet från Er på forumet - so som jag uppfattade.
Tex från Lasp

Det finns något mycket enkelt som heter "vardagen" dvs man gör något någon annan redan har gjort. Skapa ett program med egen kod enligt en förlaga som du väljer själv. Alltför många tror att dom är kungar på programmering utan att respektera användaren, kunden. Prova och maila tillbaka resultat till en liten grupp för validering. Hur mycket tränade Björn Borg och Ingemar Stenmark på sin tid.
På det viset blir man proffs. Dvs varje problem måste lösas.

Naturligtvis vill jag ha ett som fungerar, men samtidigit vill jag förstå och lära mig hur man "skall" tänka...

Medlem sedan juni 200032 967 inlägg
#23

plelkes skrev:

Naturligtvis vill jag ha ett som fungerar, men samtidigit vill jag förstå och lära mig hur man "skall" tänka...

Så trevligt, det var egentligen det svaret jag hoppats på. Målet måste vara att lära sig saker. :)

Jag kikar lite mer på koden efter fotbollen.

BBL alltså. ;)

Mvh

Medlem sedan mars 2002823 inlägg
#24

@nders,

Så trevligt, det var egentligen det svaret jag hoppats på. Målet måste vara att lära sig saker

Tyvär har jag den (dåliga) egenskapen att för att lära mig ngt så MÅSTE jag förstå det ngn lär ut

Medlem sedan juni 200032 967 inlägg
#25

Det är lite lustigt, för jag förstår när det blir fel i kalendern, men jag ser inte på rak arm hur man skulle lösa det. :l

Det verkar som att det endast blir konstigt när månaden börjar på en söndag, och enda lösningen jag kom på nu, är en ful workaround. Det är ju egentligen inte att rekommendera, utan man ska ju alltid gå till botten med problemen. Men, jag gjorde i alla fall en kontroll, "Om månaden börjar med en söndag, skriv ut en svart tabellrad med en etta i kolumnen längst till höger". Så här ser min fula fix ut (jag har bara lagt till det fetstilta):

<%@ Language = VBSCRIPT %>
<% Option Explicit %>

<HTML>
<BODY>

<%

   'Next, we need to obtain the current
   'date.  To do this, we will store the result of the
   'Date() function into a variable named dbCurrentDate
   Dim dbCurrentDate
   dbCurrentDate = "6/1/2003"

   'Now, we need to display a calendar.  At most, a calendar
   'can have six weeks.  Since a week contains seven days,
   'we will show, at most, 42 calendar cells.  We will use
   'a TABLE to generate this calendar

   'We will create an array that will store the 42 possible
   'days of the month.
   Dim aCalendarDays(42)

   'Into aCalendarDays, we will place the days of the current
   'month.  We will use the DatePart function to determine
   'when the first day of the month is
   Dim iFirstWeekday
   iFirstWeekday = DatePart("w",DateSerial(Year(dbCurrentDate), Month(dbCurrentDate), 1))

   'Now, we want to loop from 1 to the number of days in the
   'current month, populating the array aCalendarDays
   'Loopen gör ju att värdet: ( iLoop + iFirstWeekday - 1) ändras för varje varv 
   'loopen gör (iLoop räknas ju upp ett snäpp). Då blir det ju som så att först får då 
   'aCalendarDays(4) sitt värde, nästa varv får aCalendarDays(5) sitt värde osv. 
    'iLoop är ju själva räknaren som räknar upp, startar på 1, därav dras det sen bort -1
	'alternativet borde ju kunna vara att börja räkna från 0 i stället. 
    'iFirstWeekday är ju med för att den inte ska börja räkna på första dagen i veckan, utan 
	'första dagen i månaden.
	'iLoop = antalet dagar i aktuella månaden

   Dim iDaysInMonth
   iDaysInMonth = DatePart("d",DateSerial(Year(dbCurrentDate), Month(dbCurrentDate)+1, 1-1))
   Dim iLoop
   For iLoop = 1 to iDaysInMonth
      aCalendarDays(iLoop + iFirstWeekday - 2) = iLoop
   Next

   'Now that we have our populated array, we need to display the
   'array in calendar form.  We will create a table of 7 columns,
   'one for each day of the week.  The number of rows we will use
   'will be 6, the total number of possible rows, minus 42 (the upper 
   'bound of the aCalendarDays array) minus the last array position
   'used (iFirstWeekday + iDaysInMonth) divided by seven, the number of
   'days in the week!  Simple, eh!!  
   Dim iColumns, iRows
   iColumns = 7
   iRows = 6 - Int((42 - (iFirstWeekDay + iDaysInMonth)) / 7)
   '(iFirstWeekDay + iDaysInMonth) = totala antalet celler som behövs

   'Now, create the table
%>

   <TABLE ALIGN=CENTER BORDER=1 CELLSPACING=1 WIDTH=75% HEIGHT=75% ID="Table1">
     <TH COLSPAN=7>
        <FONT SIZE=+2>
<%
   'Display the month and year
   Response.Write GetMonthName(Month(dbCurrentDate))
   Response.Write ", " & Year(dbCurrentDate)
%>
        </FONT>
     </TH>
<%
   Response.Write "<TR><TD><CENTER><B>"
  Response.Write "Måndag"  
  Response.Write "</B></CENTER></TD><TD><CENTER><B>"
  Response.Write "Tisdag"
   Response.Write "</B></CENTER></TD> <TD><CENTER><B>"
  Response.Write "Onsdag" 
  Response.Write "</B></CENTER></TD><TD><CENTER><B>"
  Response.Write "Torsdag"
  Response.Write "</B></CENTER></TD><TD><CENTER><B>"
  Response.Write "Fredag"
  Response.Write "</B></CENTER></TD><TD><CENTER><B>"
  Response.Write "Lördag"
  Response.Write "</B></CENTER></TD><TD><CENTER><B>"
  Response.Write "Söndag"
  Response.Write "</B></CENTER></TD></TR>"
  
   'Now, loop through 1 through iRows, then 1 through iColumns
   Dim iRowsLoop, iColumnsLoop
[b]   If Cstr(aCalendarDays(0)) =  "1" then
		'The week starts with a sunday, do special stuff
		Response.Write "<TR BGCOLOR=""BLACK""><TD> </TD><TD> </TD><TD> </TD><TD> </TD><TD> </TD><TD> </TD>"
		Response.Write "<TD VALIGN=TOP ALIGN=RIGHT WIDTH=""14%"" BGCOLOR=""WHITE"">1</TD></TR>"
   end if[/b]
   For iRowsLoop = 1 to 6
     'Create a new row
     Response.Write "<TR>"
     For iColumnsLoop = 1 to 7
       'Create a new column
       'If there is a day there, display it, else black out the cell
		If aCalendarDays((iRowsLoop-1)*7 + iColumnsLoop)="" then
			'Black out the cell
			Response.Write "<TD BGCOLOR=BLACK> </TD>"
		Else
			'Display the date
			Response.Write "<TD VALIGN=TOP ALIGN=RIGHT WIDTH=""14%"">"
			Response.Write aCalendarDays((iRowsLoop-1)*7 + iColumnsLoop)
			Response.Write "</TD>"
		End If

     Next

     'Close the row
     Response.Write "</TR>"
   Next
%>

   </TABLE>
</BODY>
</HTML>

Mvh,

Medlem sedan mars 2002823 inlägg
#26

Tack @nders, även om det är en

ful workaround

Ngra frågor bara (så att jag lär mig oxå :stud ):
Du skrev

If Cstr(aCalendarDays(0)) =  "1" then

Varför använder du just denna konstruktion? funkar även med

If aCalendarDays(0)=  "1" then

Ibland ser man att datum konverteras med

CDate()

Detta använder "vi" inte. Skulle "omvandlingen ha ngra fördelar?

Medlem sedan juni 200032 967 inlägg
#27

Varför använder du just denna konstruktion?

Jag har för vana att alltid se till att mina datatyper garanterat är jämförbara. I det här fallet fungerar det, precis som du påpekar att utelämna cstr().

Detta använder "vi" inte. Skulle "omvandlingen ha ngra fördelar?

Det är många funktioner som kräver att ett värde är av subtypen datum för att du ska kunna använda dem. Jag är faktiskt förvånad att det fungerade så bra med dbCurrentDate = "6/1/2003" Jag hade skrivit antingen dbCurrentDate = #2003-06-01# eller dbCurrentDate = CDate("2003-06-01"). Jag hade också lagt till Session.LCID=1053 överst i dokumentet för att vara säker på att få svenska datumformat och datumnamn.

Mvh

Medlem sedan mars 2002823 inlägg
#28

@nders, tack för att du offrar tid på mig :bire
3 frågor till:

Jag har för vana att alltid se till att mina datatyper garanterat är jämförbara.

Det låter som en mycket bra och lovvärd vana, men hur skall en stackars nybörjare som jag veta detta?

Du använder

Cstr()

för att konvertera numeriskt värde till string, eller hur? - är det samma tänkande som för CDate? Vilka tillfällen skall detta användas?

Det är många funktioner som kräver att ett värde är av subtypen datum för att du ska kunna använda dem

Kan Du ge exempel på dessa funktioner? Och finns det tillfälle då det är direkt felaktigt att använda CDate()?

Medlem sedan juni 200032 967 inlägg
#29

Det låter som en mycket bra och lovvärd vana, men hur skall en stackars nybörjare som jag veta detta?

Det vet inte en stackars nybörjare, det är däremot något som en stackars nybörjare lär sig, till exempel vid ett dylikt tillfälle. :)

Du använder Cstr() för att konvertera numeriskt värde till string, eller hur?

Ja och nej - jag använder Cstr() för att konvertera värde av någon typ till en sträng. Det kan vara ett värde av en taltyp, eller datumtyp exempelvis.

är det samma tänkande som för CDate? Vilka tillfällen skall detta användas?

Ja, Cstr() och CDate() är närbesläktade funktioner, de konverterar bara värdet till olika subtyper. Ett bra exempel på när du oftast är tvungen att göra en konvertering med CDate() är vid en jämförelse mellan ett inmatat värde och dagens datum.

' Exempel som skall vara felaktigt eftersom en sträng med ett datum i aldrig är samma sak som ett datumvärde: 
strDate = Request.Form("datum")
' kolla om man matat in idag
if strDate = date then
   ' jäää!
end if

' Fungerande exempel:
strDate = Request.Form("datum")
[b]strDate = CDate(strDate)[/b]
' kolla om man matat in idag
if strDate = date then
   ' jäää!
end if

Kan Du ge exempel på dessa funktioner? Och finns det tillfälle då det är direkt felaktigt att använda CDate()?

Exempel på funktioner som normalt (hrmpf) kräver att mottaget värde är av subtypen datum är flera av de du använt i din kod. FormatDateTime(), WeekDay(), DatePart(), DateDiff(), Year(), osv.

Ja, det finns tillfällen då det är direkt felaktigt att använda CDate. Alla värden är nämligen inte direkt konverterbara till datum. Om du har en sträng som innehåller inte endast består av ett datum, då kommer du få ett felmeddelande, type mismatch. Därför bör man, om man inte vet att variabelinnehållet alltid är ett giltigt datum, kontrollera med IsDate() innan man försöker sig på en konvertering till subtypen datum. Ett exempel är om en användare ska mata in ett datum manuellt i ett formulär, då vet du ju inte med säkerhet att datumet är giltigt.

If IsDate(strDatum) then
 ' jepp, det är ett datum, gör det du ska
else
 ' nepp, inget datum, visa meddelande för användaren, "gör om gör rätt"!
end if

Hoppas en del klarnat i alla fall.

Mvh,

Medlem sedan mars 2002823 inlägg
#30

Tack @nders,
jag börjar i alla fall skymta ljuset :birp

Medlem sedan mars 2002823 inlägg
#31

Kom just att tänka på en sak:
Om jag vill modifiera min almanacka genom att använda mig droppdown där man kan välja månad och år. Och säg att formulären heter monad och ar.
Då kan jag väl använda mig av:

strMonth= Request.Form("monad")
strMonth= CDate(strMonth)

'och
strYear= Request.Form("ar")
strYear = CDate(strYear)
Medlem sedan juni 200032 967 inlägg
#32

Nja. CDate() kräver att du skickar ett komplett datum. Jag hade byggt ihop ett datum i en sträng, och kört cdate() på den:

strDate = Request.Form("ar") & "-" & Request.Form("monad") & "-01"
dteDate = CDate(strDate)

Mvh

Medlem sedan dec. 20003 887 inlägg
#33

Nu avviker jag en hel del från trådens anda: Det är bättre om du kommer på saker själv. Jag svarar med hur jag skulle ha löst det hela... förvisso vet jag inte om det fungerar som jag tänkt, eftersom jag inte har någon möjlighet att testa koden ;)

Men det är egentligen bara ett annat (enklare, tycker jag) sätt att räkna

Dim dteCurrentDate, dteFirstDay, intFirstDayIndex, intLastDayIndex, a_intKalender(42), strHTML

dteCurrentDate = DateSerial(Request.Form("ar"), Request.Form("monad"), 1)
intFirstDayIndex = WeekDay(dteCurrentDate, 1), 2) - 1
intLastDayIndex = IntFirstDayIndex - 1 + DatePart("d", (DateAdd("m", 1, dteCurrentDate) - 1))

For i = intFirstDayIndex To intLastDayIndex
  a_intKalender(i) = i - 5
Next

strHTML = "<table align=""center"" border=""1"" cellspacing=""1"" width=""75%"" height=""75%"" id=""table1"">"
strHTML = strHTML & "<th colspan=""7""><font size=""+2"">"
strHTML = strHTML & GetMonthName(Month(dteCurrentDate)) & ", " & Year(dteCurrentDate)
strHTML = strHTML & "</font></th>"
strHTML = strHTML & "<tr><td style=""text-align: center; font-weight: bold;"">Måndag</td>" & _
  "<td style=""text-align: center; font-weight: bold;"">Tisdag</td>" & _
  "<td style=""text-align: center; font-weight: bold;"">Onsdag</td>" & _
  "<td style=""text-align: center; font-weight: bold;"">Torsdag</td>" & _
  "<td style=""text-align: center; font-weight: bold;"">Fredag</td>" & _
  "<td style=""text-align: center; font-weight: bold;"">Lördag</td>" & _
  "<td style=""text-align: center; font-weight: bold;"">Söndag</td>"

For i = 0 To 41
  If i mod 7 = 0 Then strHTML = strHTML & "<tr>"

  If a_intKalender(i) = "" Then
    strHTML = strHTML & "<td bgcolor=""black""> </td>"
  Else
    strHTML = strHTML & "<td valign=""top"" align=""right"" width=""14%"">" & a_intKalender(i) & "</td>"
  End If

  If i mod 6 = 0 And i <> 0 Then strHTML = strHTML & "</tr>"
Next

strHTML = strHTML & "</table></body></html>"

Response.Write strHTML
Medlem sedan mars 2002823 inlägg
#34

Tack Engine för ditt försök.
Kan tyvärr inte testa det hela för jag får nedanstående felmess

Microsoft VBScript compilation error '800a0401'

Expected end of statement

/plelkesprojekt/engine.asp, line 9

intFirstDayIndex = WeekDay(dteCurrentDate, 1), 2) - 1
---------------------------------------------^

Ber dig dock att förklara vissa kodsnuttar:

intFirstDayIndex = WeekDay(dteCurrentDate, 1), 2) - 1
  • vad står "dte" för?
  • kan du förklara hur du tänker när du konstruerar kodsnutten?
For i = intFirstDayIndex To intLastDayIndex
  a_intKalender(i) = i - 5

varför "i-5"?

If i mod 7 = 0

Vad betyder "mod"?

Medlem sedan mars 2002823 inlägg
#35

kom på en sak till:
om jag använder nedanstående kodsnutt:

Session.LCID=1053 
dNewDate = Year(Date()) & "-" & Month(Date()) & "-" & 1iDayMonth = DatePart("d", DateSerial(Year(Date()), Month(Date())+1, 0)) 'dvs sista dagen månad innan
For iDag = 1 to iDayMonth
aKalender(iDag) = DatePart("w",Year(Date()) & "-" & Month(Date()) & "-" & iDag)
Next
  1. Genom Session.LCID=1053 anger jag ju att det rör sig om Sverige, och i Sverige börjar ju veckorna på Måndagar - borde inte detta räcka?
  2. kan jag skriva ngn kod/funktion där vbMonday är weekday=1?
Medlem sedan dec. 20003 887 inlägg
#36

Oj... småmissar där

intFirstDayIndex = WeekDay(dteCurrentDate, 2) - 1

dte står för Date

Loopen placerar ut datumen på "rätt plats" i Arrayen.
Eftersom a_intKalender går från 0 till 41, så startar jag helt enkelt på (veckodagsnumret för den första den sökta månaden) - 1. -1 så att inte indexet blir galet.

i-5 är inte rätt ser jag nu... jag som tänkte för fort där. Det är enklare att göra så här

Dim intDay: intDay = 1
For i = intFirstDayIndex To intLastDayIndex
  a_intKalender(i) = intDay
  intDay = intDay + 1
Next

mod är samma som division med rest: 7 mod 6 = 1, 7 mod 7 = 0...
Mod står för modulo om jag inte missminner mig.

Medlem sedan mars 2002823 inlägg
#37

Ursäkta Engine, men nu

Loopen placerar ut datumen på "rätt plats" i Arrayen.
Eftersom a_intKalender går från 0 till 41, så startar jag helt enkelt på (veckodagsnumret för den första den sökta månaden) - 1. -1 så att inte indexet blir galet.

fattar jag nada...

Medlem sedan dec. 20003 887 inlägg
#38

Månaden representeras ju så här:

M   T  O  T  F  L  S
0   1  2  3  4  5  6
7   8  9 10 11 12 13
...
35 36 37 38 39 40 41

intFirstDayIndex = WeekDay("2003-06-01", 2) - 1 (= 6)

Denna månads första dag är alltså en söndag. 2 = vbMonday.

I loopen ska alltså datum 1 sättas in i arrayen på index 6.

Medlem sedan mars 20015 287 inlägg
#39
For i = 0 To 41
  If i mod 7 = 0 Then strHTML = strHTML & "</tr><tr>"

  If a_intKalender(i) = "" Then
    strHTML = strHTML & "<td bgcolor=""black""> </td>"
  Else
    strHTML = strHTML & "<td valign=""top"" align=""right"" width=""14%"">" & a_intKalender(i) & "</td>"
  End If

Next

Eller?

Medlem sedan dec. 20003 887 inlägg
#40

Gör man så, vilket också fungerar, bör man inte glömma att lägga till en "<tr>" innan loopen...

390 ms totalt · 4 externa anrop · v20260731065814-full.1dc6f849
121 ms — deklarationer (db)
125 ms — hämta statistik (db)
142 ms — hämta tråd, inlägg och bilagor (db)
121 ms — ändringar (db)