#! /usr/bin/perl # Copyright 2001-2007 Leslie Richardson # This file is part of Open Admin for Schools. # Open Admin for Schools is free software; you can redistribute it # and/or modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # ======= Monthly Student Attendance Report ======= # Get passed date for end of calendar month or school month. # Calculate days in the month and number of days of school hols. # Get student absences for that month, order by group,lastname,firstname. # Do # of present, absent, late for month. # Absent strings for matching set in admin.conf; Comparison at line # 305 in this file. my %lex = ('Monthly Attendance Report' => 'Monthly Attendance Report', 'Date format Error' => 'Date format Error', 'Main' => 'Main', 'Attendance' => 'Attendance', 'Schooldays' => 'Schooldays', 'Weekdays' => 'Weekdays', 'Holidays' => 'Holidays', 'Hols/Inserv' => 'Hols/Inserv', 'Red = Withdrawn' => 'Red = Withdrawn', 'Grand Totals' => 'Grand Totals', 'Periods Per Day not defined for' => 'Periods Per Day not defined for', 'Name' => 'Name', 'Enrolled' => 'Enrolled', 'Attended' => 'Attended', 'Days' => 'Days', 'Absent' => 'Absent', 'Unexec' => 'Unexec', 'Excuse' => 'Excuse', 'Other' => 'Other', 'Total' => 'Total', 'Late' => 'Late', 'Times' => 'Times', 'Grade' => 'Grade', 'homeroom' => 'homeroom', 'band' => 'band', 'Error: Total School Days not calculated' => 'Error: Total School Days not calculated', 'Student-Days' => 'Student-Days', 'Enrollment Error for student' => 'Enrollment Error for student', 'Records are not consistent' => 'Records are not consistent', 'Pg' => 'Pg', 'Top' => 'Top', 'View Log File' => 'View Log File', ); use DBI; use CGI; use Date::Business; my $maxlines = 24; # Maximum records per PDF page. # Read config variables require "../etc/admin.conf" || die "Cannot read admin.conf!"; my @month = ('','January','February','March','April','May','June','July', 'August','September','October','November','December'); my @tim = localtime(time); my $year = @tim[5] + 1900; my $month = @tim[4] + 1; my $day = @tim[3]; if (length($month) == 1){ $month = "0".$month;} if (length($day) == 1){ $day = "0".$day;} my $currdate = "$year-$month-$day"; my $q = new CGI; print $q->header; my %arr = $q->Vars; # Setup the TYPE of report, HTML or PDF. my $html = $arr{html}; my $pdf = $arr{pdf}; # It had better be: YYMMDD or die... if (not $arr{date} or length($arr{date}) != 6) { print $lex{'Date format Error'}. " (yymmdd)\n"; die "$lex{'Date format Error'} (yymmdd)\n"; print "\n"; } my $mon = substr($arr{date},2,2); my $enddate = $arr{date}; my $group = $arr{group}; # Either 'grade', 'homeroom', or 'band'. # Check to make sure start date can really be the first of month. my ($null, $startmonth, $null1) = split /-/,$schoolstart; if ($mon == $startmonth) { $schoolstart =~ s/-//g; $startdate = $schoolstart; } else { $startdate = "20".substr($enddate,0,-2)."01"; } $enddate = "20".$enddate; my $end = new Date::Business(DATE=>$enddate); my $start = new Date::Business(DATE=>$startdate); my $schooldays = $end->diffb($start,'prev','next'); $schooldays++; # Yup, this is the right way to do the date calcs...checked.. my $dsn = "DBI:$dbtype:dbname=$dbase"; my $dbh = DBI->connect($dsn,$user,$password); my $sth = $dbh->prepare("select * from dates where to_days(date) >= to_days('$startdate') and to_days(date) <= to_days('$enddate')"); $sth->execute; if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; } my $holidays = $sth->rows; my $daysinsession = $schooldays - $holidays; if ( $pdf ) { # Open TEX file, and print header. $shortname = "monthatt$$"; $fileName = "$shortname.tex"; open(TEX,">$fileName") || die "Can't open tex file"; print_tex_doc_start(); # Setup the start of the file. } # Page Header... print "$doctype\n". $lex{'Monthly Attendance Report'}. " $chartype\n[ ". $lex{Main}. " |\n"; print "". $lex{'Attendance'}. " ]
\n"; if ($html){ # print top of page print '

'. $lex{'Monthly Attendance Report'}. " - $month[$mon]

\n"; print '

'. $lex{Schooldays}. ": $daysinsession   ". $lex{Weekdays}; print ": $schooldays   ". $lex{'Hols/Inserv'}. ": $holidays

\n"; print "

[ ". $lex{'Grand Totals'}. " ] \n"; print "". $lex{'Red = Withdrawn'}. "

\n"; } my $select; $sth = $dbh->prepare("select * from studentall $select order by $group, lastname, firstname"); $sth->execute; if ($DBI::errstr) { print $DBI::errstr; die;} my $studrows = $sth->rows; # Setup statement handle to find which table student is in. my $sth5 = $dbh->prepare("select studnum from student where studnum = ?"); my $curroom = -1; # Watch! Not a value entered for a reason...hopefully. my $firstflag = 1; # Flag to watch for first "real" person (not withdrawn) my $studentname; # *********** Start of Main Loop *********** while (my @student = $sth->fetchrow){ $student[1] =~ s/\\/\//g; $studentname = "$student[1], $student[2] $student[3]"; # Now let's find which table student from: student or studentwd $sth5->execute($student[4]); if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; } my $active = $sth5->rows; # returns 1 if in student, 0 if not. if (not $active and $html){ $studentname = "$studentname"; } # Calculate the days enrolled for this student # Return blocks of time when student was enrolled. #(An array of hash pointers) @enrolblocks = &find_enrollment_blocks($student[4],$active); $schooldays = 0; #print "
$student[2] $student[1] ($student[4])
\n"; foreach my $hashref (@enrolblocks){ my $startenroldate = $hashref->{start}; my $endenroldate = $hashref->{end}; $startenroldate =~ s/-//g; $endenroldate =~ s/-//g; # strip hyphens $endenrolobj = new Date::Business(DATE=>$endenroldate); $startenrolobj = new Date::Business(DATE=>$startenroldate); # The other objects are $start and $end. # Now figure out the overlap and actual reporting period dates. my $startdiff = $start->diffb($startenrolobj,'prev','next'); my $enddiff = $end->diffb($endenrolobj,'prev','next'); #print "SEnrol: $startenroldate EEnrol: $endenroldate
\n"; #print "SReport: ",$start->image," EReport:",$end->image,"
\n"; #print "SD: $startdiff ED: $enddiff
\n"; if ($startdiff < 0){ # Actual starting time is later. $startrpobj = new Date::Business(DATE =>$startenroldate); } else { $startrpobj = new Date::Business(DATE=>$startdate);} if ($enddiff > 0){ # Actual ending date is earlier. $endrpobj = new Date::Business(DATE=>$endenroldate); } else { $endrpobj = new Date::Business(DATE=>$enddate);} my $rpdays = $endrpobj->diffb($startrpobj,'prev','next'); $rpdays++; if ($rpdays < 0){ $rpdays = 0;} my $startrp = $startrpobj->image; my $endrp = $endrpobj->image; #print "StartRP: $startrp EndRP: $endrp
\n"; #print "RP Days: $rpdays
\n"; if ($rpdays){ # Now find number of holidays during this same period. $sth4 = $dbh->prepare("select * from dates where to_days(date) >= to_days('$startrp') and to_days(date) <= to_days('$endrp')"); $sth4->execute; if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; } $rphols = $sth4->rows; } else { $rphols = 0;} #print "RPHols: $rphols

\n"; $schooldays = $schooldays + $rpdays - $rphols; #print "School Days: $schooldays
\n"; } # End of Loop finding Student Enrollment if ($schooldays < 1){ next; } # Put Header printing here since we have to skip some students ==== $oldroom = $curroom; if ($group eq $lex{'homeroom'}){ $curroom = $student[6]; # homeroom field. # Get Teacher Name for the room. $sth1 = $dbh->prepare("select lastname, firstname from staff where homeroom = '$curroom' "); $sth1->execute; if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; } my ($fn, $ln) = $sth1->fetchrow; $teachername = '$fn $ln'; } elsif ($group eq $lex{'band'}) { $curroom = $student[58]; # band } else { $curroom = $student[5]; # grade field. } if ($curroom ne $oldroom) { if (not $firstflag) { if ($html){ print_html_class_totals(); } else { print_tex_class_totals(); $linecount=0; } $totschooldays = 0; $totattended = 0; $totlatedayun = 0; $totlatedayex = 0; $totabsentdayun = 0; $totabsentdayex = 0; $totother = 0; $totabsenttot = 0; } if ($html){ print "

"; print_html_header();} else { print_tex_header(); } # Recalc the number of periods per day when class changes. $periods = $g_ppd{$student[5]}; # student[5] is grade. if (not $periods){ if (not $student[5]){ $student[5] = 'Undefined!';} print '

'. $lex{'Periods Per Day not defined for'}. ' '. $lex{Grade}. " $student[5]\n"; print "$student[2] $student[1]

\n"; print "\n"; die; } } # End of Header printing section =========== # Note: this can use startdate and $enddate since we only track absences # Get attendance records for this student and loop through adding up. $sth1 = $dbh->prepare("select * from attend where studentid='$student[4]' and to_days(absdate) >= to_days('$startdate') and to_days(absdate) <= to_days('$enddate') order by absdate,period"); $sth1->execute; if ($DBI::errstr) { print $DBI::errstr; die; } $absentex = 0;$absentun = 0; $lateex = 0;$lateun = 0; $other = 0; # Track 5 groups of attendance: Absent Unexcused, Absent (any # other; presumed excused), Late Unexcused, Late (any other; # presumed excused), Other (which should be 0). while (@absence = $sth1->fetchrow){ my $reason = $absence[3]; # These string values set in the admin.conf file and match reasons if ($reason =~ /$absentUnexcused/) { $absentun++; } elsif ($reason =~ /$absentString/){ $absentex++;} elsif ($reason =~ /$lateUnexcused/) { $lateun++; } elsif ($reason =~ /$lateString/) { $lateex++; } else { $other++;} } if (not $periods){ if (not $student[5]){ $student[5] = 'Undefined!';} print '

'. $lex{'Periods Per Day not defined for'}. ' '. $lex{Grade}. "# $student[5]\n"; print "$student[2] $student[1].

\n"; print "\n"; die; } $absentdayun = $absentun/$periods; # convert from periods into days $absentdayex = $absentex/$periods; $otherday = $other/$periods; $absentperun = ($absentdayun/$schooldays) * 100; $absentperex = ($absentdayex/$schooldays) * 100; $otherper = ($otherday/$schooldays) * 100; $absentdaytot = $absentdayun + $absentdayex + $otherday; $absentpertot = ($absentdaytot/$schooldays) * 100; $latedayun = $lateun/$periods; $latedayex = $lateex/$periods; $lateperun = ($latedayun/$schooldays) * 100; $lateperex = ($latedayex/$schooldays) * 100; $attended = $schooldays - $absentdaytot; # For Class/Grade Summary $totschooldays = $schooldays + $totschooldays; $totattended = $attended + $totattended; $totabsentdayun = $absentdayun + $totabsentdayun; $totabsentdayex = $absentdayex + $totabsentdayex; $totother = $otherday + $totother; $totabsenttot = $absentdaytot + $totabsenttot; $totlatedayun = $latedayun + $totlatedayun; $totlatedayex = $latedayex + $totlatedayex; # For School Summary at Bottom $grtotschooldays += $schooldays; $grtotattended += $attended; $grtotabsentdayun += $absentdayun; $grtotabsentdayex += $absentdayex; $grtotother += $otherday; $grtotabsenttot += $absentdaytot; $grtotlatedayun += $latedayun; $grtotlatedayex += $latedayex; $firstflag = 0; # Not first person to run through. # Print this student's record if ($html){ print_html_record(); } else { print_tex_record($student[1], $student[2], $student[3], $student[4]); } $linecount++; if ($pdf and $linecount >= $maxlines){ # New page. print TEX "\\end{tabular}\\newpage\n\n"; print_tex_header(); $linecount = 0; } } # End of main loop # print out stats for the last class if ($html){ print_html_class_totals(); } else { print_tex_class_totals(); } # Grand totals if ($html){ print_html_grandtotals(); } else { print_tex_grandtotals(); print_tex_end(); } # ================ # Functions # ================ # Print Table header at top of each table. #-------------------- sub print_html_header { #-------------------- $heading = "\L\u$group"; print ""; print ""; print '\n"; print '\n"; print '\n"; print '\n"; } #------------------- sub print_tex_header { #------------------- $heading = "\L\u$group"; print TEX "\\begin{tabular}{|p{5cm}"; for (1..8){ print TEX "|p{1.4cm}";} print TEX "|}\n\\hline\\rowcolor[gray]{0.85}{\\it $heading:} "; print TEX "{\\bf\\large $curroom} \n"; print TEX "& {\\bf ". $lex{Enrolled}. ' ('. $lex{Days}. ")} & {\\bf "; print TEX $lex{Attended}. ' ('. $lex{Days}. ")} & "; print TEX "{\\bf ". $lex{Absent}. ' '. $lex{Unexec}. ' ('. $lex{Days}; print TEX ")} &{\\bf ". $lex{Absent}. ' '. $lex{Excuse}. ' ('. $lex{Days}. ")} & "; print TEX "{\\bf ". $lex{Absent}. ' '. $lex{Other}. ' ('. $lex{Days}. ")} &{\\bf "; print TEX $lex{Absent}. ' '. $lex{Total}. ' ('. $lex{Days}. ")} & \n"; print TEX "{\\bf ". $lex{Late}. ' '. $lex{Unexec}. ' ('. $lex{Times}. ")} &{\\bf "; print TEX $lex{Late}. ' '. $lex{Excuse}. ' ('. $lex{Times}. ")}\\\\ \\hline\n"; } #-------------------------- sub print_html_class_totals { #-------------------------- if (not $totschooldays){ print $lex{'Error: Total School Days not calculated'}. "!\n"; return; } $totpercent = ($totattended/$totschooldays) * 100; $totabsentperun = ($totabsentdayun/$totschooldays) * 100; $totabsentperex = ($totabsentdayex/$totschooldays) * 100; $tototherper = ($totother/$totschooldays) * 100; $totabsentpertot = ($totabsenttot/$totschooldays) * 100; $totlateperun = ($totlatedayun/$totschooldays) * 100; $totlateperex = ($totlatedayex/$totschooldays) * 100; # print out stats for this class print ""; print ""; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "

$heading: $curroom

'. $lex{Name}. ''. $lex{Enrolled}. ''; print $lex{'Attended'}. '
('. $lex{Days}. ")
'. $lex{Absent}. '
'. $lex{Unexec}. '
('. $lex{Days}. ')
'; print $lex{Absent}. '
'. $lex{Excuse}. '
('. $lex{Days}. ")
'. $lex{Absent}. '
'. $lex{Other}. '
('. $lex{Days}. ')
'. $lex{Absent}; print '
'. $lex{Total}. '
('. $lex{Days}. ")
'. $lex{Late}. '
'. $lex{Unexec}. '
('. $lex{Times}. ')
'; print $lex{Late}. '
'. $lex{Excuse}. '
('. $lex{Times}. ")
". $lex{Total}. ' - ('. $lex{'Student-Days'}. ")$totschooldays$totattended
(";printf "%3.2f",$totpercent; print "%)
$totabsentdayun
("; printf"%3.2f",$totabsentperun; print "%)
$totabsentdayex
("; printf"%3.2f",$totabsentperex; print "%)
$totother
("; printf"%3.2f",$tototherper; print "%)
$totabsenttot
("; printf"%3.2f",$totabsentpertot; print "%)
$totlatedayun days
("; printf"%3.2f",$totlateperun; print "%)
$totlatedayex days
("; printf"%3.2f",$totlateperex; print "%)
\n"; } #------------------------- sub print_tex_class_totals { #------------------------- if (not $totschooldays){ print "Error: Total School Days not calculated!";return; } $totpercent = ($totattended/$totschooldays) * 100; $totabsentperun = ($totabsentdayun/$totschooldays) * 100; $totabsentperex = ($totabsentdayex/$totschooldays) * 100; $tototherper = ($totother/$totschooldays) * 100; $totabsentpertot = ($totabsenttot/$totschooldays) * 100; $totlateperun = ($totlatedayun/$totschooldays) * 100; $totlateperex = ($totlatedayex/$totschooldays) * 100; # print out stats for this class print TEX "\\rowcolor[gray]{0.90}"; print TEX "{\\bf Totals (Student-Days)} & $totschooldays &\n"; print TEX "$totattended (", sprintf("%3.2f",$totpercent),"\\%)& \n"; print TEX "$totabsentdayun (", sprintf("%3.2f",$totabsentperun),"\\%)&\n"; print TEX "$totabsentdayex (", sprintf("%3.2f",$totabsentperex),"\\%)&\n"; print TEX "$totother (", sprintf("%3.2f",$tototherper),"\\%)&\n"; print TEX "$totabsenttot (", sprintf("%3.2f",$totabsentpertot),"\\%)&\n"; print TEX "$totlatedayun days (", sprintf("%3.2f",$totlateperun),"\\%)&\n"; print TEX "$totlatedayex days (", sprintf("%3.2f",$totlateperex),"\\%)\\\\"; print TEX "\\hline\\end{tabular}\\newpage\n\n"; } #------------------------- sub find_enrollment_blocks { #------------------------- # Return a list of hash pointers to enrollment blocks. # Globals: $dbh, $currdate, $schoolstart (from admin.conf) # Passed Student Number (studnum) and active status. my $studnum = shift @_; my $active = shift @_; # Read enrollment changes from the transfer table. # Assume the $dbh var already set... my $sth = $dbh->prepare("select * from transfer where studnum = '$studnum' and to_days(date) > to_days('$schoolstart') order by date desc"); # Problem if two records of same student on same day... an entry error. $sth->execute; if ($DBI::errstr) { print $DBI::errstr; die;} #my $rows = $sth->rows; my @enrollment; # Read the first record and set the status. my @transrec = $sth->fetchrow; if (not $transrec[0]){ # no transfer records for this student if ($active){ # registered but no transfer records; my $hashref = {}; $hashref->{start} = $schoolstart; $hashref->{end} = $currdate; push @enrollment, $hashref; } return @enrollment; # return undefined if not active; # return full year if active. } my $status = ''; if ($transrec[3] eq 'enrol' or $transrec[3] eq 're-enrol'){ # Set $status and push first record.(hashref in array) $status = 'enrol'; my $hashref = {}; $hashref->{start} = $transrec[2]; $hashref->{end} = $currdate; push @enrollment, $hashref; # @enrollment is an array of hashrefs to the enrollment blocks. } else { $status = 'withdraw'; $statusdate = $transrec[2]; } while (@transrec = $sth->fetchrow){ if ($status eq 'enrol' and $transrec[3] eq 'withdraw'){ # change status $status = 'withdraw'; $statusdate = $transrec[2]; } elsif ($status eq 'withdraw' and ($transrec[3] eq 'enrol' or $transrec[3] eq 're-enrol')){ $status = 'enrol'; my $hashref = {}; $hashref->{start} = $transrec[2]; $hashref->{end} = $statusdate; push @enrollment, $hashref; } else { # Error! print "

". $lex{'Enrollment Error for student'}. ": $studnum
\n"; print $lex{'Records are not consistent'}. ".
\n"; #die "Enrollment error for $studnum"; } } # End of While. return @enrollment; } # End of Sub #---------------------- sub print_tex_doc_start { #---------------------- print TEX "\\documentclass[10pt,letterpaper,oneside]{article} \\usepackage{array,colortbl} \\pagestyle{empty} \\setlength{\\textwidth}{7.7in} \\setlength{\\textheight}{10.6in} \\setlength{\\hoffset}{-1.5in} \\setlength{\\voffset}{-0.8in} \\setlength{\\headsep}{10pt} \\setlength{\\headheight}{14pt} \\setlength{\\topmargin}{0pt} \\setlength{\\parindent}{0pt} \\setlength{\\tabcolsep}{5pt} \\setlength{\\extrarowheight}{3pt} \\pagestyle{headings} \\markright{$schoolname \\hfill ". $lex{'Monthly Attendance Report'}. " -- $month[$mon] -- ". $lex{Pg}. " } \n\n \\begin{document}\n"; } # End of Print Tex Doc Start #---------------- sub print_tex_end { #---------------- print TEX "\\hline\\end{tabular}\n\n\\end{document}\n"; close TEX; system("$pdflatex $fileName > pdflog$$.txt"); system("mv $shortname.pdf $downloaddir"); system("mv pdflog$$.txt $downloaddir"); system("rm $shortname.*"); print "

\n"; print $lex{'View/Download'}. ' '. $lex{'Monthly Attendance Report'}. "

\n"; print "

[ ". $lex{Attendance}. " |\n"; print ""; print $lex{'View Log File'}. " ]

\n"; print "\n"; } # Print Tex End #-------------------- sub print_html_record { #-------------------- print "$studentname ($student[4]) $withdrawdate"; print "$schooldays$attended\n"; print "$absentdayun ("; printf "%3.2f",$absentperun; print "%)"; print "$absentdayex ("; printf "%3.2f",$absentperex; print "%)"; print "$otherday ("; printf "%3.2f",$otherper; print "%)"; print "$absentdaytot ("; printf "%3.2f",$absentpertot; print "%)"; print "$lateun ("; printf "%3.2f",$lateperun; print "%)"; print "$lateex ("; printf "%3.2f",$lateperex; print "%)"; print "\n"; } # End of Print HTML Record #------------------- sub print_tex_record { #------------------- my ($lastname, $firstname, $middlename, $studnum) = @_; print TEX "{\\bf $lastname}, $firstname $middlename ($studnum) $withdrawdate & "; print TEX "$schooldays & $attended & "; print TEX "$absentdayun (", sprintf("%3.2f",$absentperun), "\\%)& "; print TEX "$absentdayex (", sprintf("%3.2f",$absentperex), "\\%) & "; print TEX "$otherday (", sprintf("%3.2f",$otherper), "\\%) & "; print TEX "$absentdaytot (", sprintf("%3.2f",$absentpertot),"\\%) & "; print TEX "$lateun (", sprintf("%3.2f",$lateperun), "\\%) & "; print TEX "$lateex (", sprintf("%3.2f",$lateperex), "\\%) \\\\ \\hline\n\n"; } #------------------------- sub print_html_grandtotals { #------------------------- # Print Grand Totals print "

 

\n"; print"\n"; print "\n"; print "\n"; print "\n"; print '\n"; print '\n"; $grtotpercent = ($grtotattended/$grtotschooldays) * 100; $grtotabsentperun = ($grtotabsentdayun/$grtotschooldays) * 100; $grtotabsentperex = ($grtotabsentdayex/$grtotschooldays) * 100; $grtototherper = ($grtotother/$grtotschooldays) * 100; $grtotabsentpertot = ($grtotabsenttot/$grtotschooldays) * 100; $grtotlateperun = ($grtotlatedayun/$grtotschooldays) * 100; $grtotlateperex = ($grtotlatedayex/$grtotschooldays) * 100; # print out grand totals print ""; print ""; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "

". $lex{'Grand Totals'}. "

". $lex{Enrolled}. ''. $lex{Attended}. '
('. $lex{Days}. ")
". $lex{Absent}. '
'. $lex{Unexec}. '
('. $lex{Days}. ")
\n"; print $lex{Absent}. '
'. $lex{Excuse}. '
('. $lex{Days}. ")
'. $lex{Absent}. '
'. $lex{Other}. '
('. $lex{Days}. ')
'; print $lex{Absent}. '
'. $lex{Total}. '
('. $lex{Days}. ")
'. $lex{Late}. '
'. $lex{Unexec}. '
('. $lex{Times}. ')
'; print $lex{Late}. '
'. $lex{Excuse}. '
('. $lex{Times}. ")
Grand Totals (Student-Days)$grtotschooldays$grtotattended days
(";printf "%3.2f",$grtotpercent; print "%)
$grtotabsentdayun days
("; printf"%3.2f",$grtotabsentperun; print "%)
$grtotabsentdayex days
("; printf"%3.2f",$grtotabsentperex; print "%)
$grtotother days
("; printf"%3.2f",$grtototherper; print "%)
$grtotabsenttot days
("; printf"%3.2f",$grtotabsentpertot; print "%)
$grtotlatedayun
("; printf"%3.2f",$grtotlateperun; print "%)
$grtotlatedayex
("; printf"%3.2f",$grtotlateperex; print "%)
\n"; print "

[ ". $lex{Main}. " |\n"; print "". $lex{Attendance}. " |\n"; print "". $lex{Top}. " ]

\n"; } #------------------------ sub print_tex_grandtotals { #------------------------ print TEX "\\begin{tabular}{|p{4cm}"; for (1..8){ print TEX "|p{1.5cm}";} print TEX "|}\n\\hline\\rowcolor[gray]{0.85}". $lex{Grand}. ' '. $lex{Totals}. " &"; print TEX $lex{Enrolled}. " & ". $lex{Attended}. " (". $lex{Days}. ") &"; print TEX $lex{Absent}. ' '. $lex{Unexec}. " (". $lex{Days}. ") & ". $lex{Absent}; print TEX ' '. $lex{Excuse}. " (". $lex{Days}. ") &"; print TEX $lex{Absent}. ' '. $lex{Other}. " (". $lex{Days}. ") & ". $lex{Absent}; print TEX ' '. $lex{Total}. " (". $lex{Days}. ") &"; print TEX $lex{Late}. ' '. $lex{Unexec}. " (". $lex{Times}. ") & ". $lex{Late}; print TEX ' '. $lex{Excuse}. " (". $lex{Times}. ")\\\\ \\hline\n"; $grtotpercent = ($grtotattended/$grtotschooldays) * 100; $grtotabsentperun = ($grtotabsentdayun/$grtotschooldays) * 100; $grtotabsentperex = ($grtotabsentdayex/$grtotschooldays) * 100; $grtototherper = ($grtotother/$grtotschooldays) * 100; $grtotabsentpertot = ($grtotabsenttot/$grtotschooldays) * 100; $grtotlateperun = ($grtotlatedayun/$grtotschooldays) * 100; $grtotlateperex = ($grtotlatedayex/$grtotschooldays) * 100; # print out grand totals print TEX $lex{Grand}. ' '. $lex{Total}. " (". $lex{'Student-Days'}. ") & $grtotschooldays &"; print TEX "$grtotattended ". $lex{days}. " (",sprintf("%3.2f",$grtotpercent),"\\%)&\n"; print TEX "$grtotabsentdayun ". $lex{days}. " (",sprintf("%3.2f",$grtotabsentperun),"\\%)&\n"; print TEX "$grtotabsentdayex ". $lex{days}. " (",sprintf("%3.2f",$grtotabsentperex),"\\%)&\n"; print TEX "$grtotother ". $lex{days}. " (",sprintf("%3.2f",$grtototherper),"\\%)&\n"; print TEX "$grtotabsenttot ". $lex{days}. " (",sprintf("%3.2f",$grtotabsentpertot),"\\%)&\n"; print TEX "$grtotlatedayun (",sprintf("%3.2f",$grtotlateperun),"\\%)&\n"; print TEX "$grtotlatedayex (",sprintf("%3.2f",$grtotlateperex),"\\%)\\\\ \n"; } # End of Print_tex_grandtotals