--- loncom/interface/Attic/lonspreadsheet.pm 2002/11/05 15:00:27 1.133 +++ loncom/interface/Attic/lonspreadsheet.pm 2002/11/07 15:37:02 1.135 @@ -1,5 +1,5 @@ # -# $Id: lonspreadsheet.pm,v 1.133 2002/11/05 15:00:27 matthew Exp $ +# $Id: lonspreadsheet.pm,v 1.135 2002/11/07 15:37:02 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -62,6 +62,8 @@ use GDBM_File; use HTML::TokeParser; use Apache::lonhtmlcommon; use Apache::loncoursedata; +use Apache::File(); +use Spreadsheet::WriteExcel; # # Caches for coursewide information # @@ -1107,9 +1109,8 @@ sub exportdata { # ========================================================== End of Spreadsheet # ============================================================================= - # -# Procedures for screen output +# Procedures for spreadsheet output # # --------------------------------------------- Produce output row n from sheet @@ -1143,9 +1144,15 @@ sub sort_indicies { return @sortidx; } -######################################################################## -######################################################################## - +############################################################# +### ### +### Spreadsheet Output Routines ### +### ### +############################################################# + +############################################ +## HTML output routines ## +############################################ sub html_editable_cell { my ($cell,$bgcolor) = @_; my $result; @@ -1177,9 +1184,6 @@ sub html_uneditable_cell { return ' '.$value.' '; } -######################################################################## -######################################################################## - sub outsheet_html { my ($sheet,$r) = @_; my ($num_uneditable,$realm,$row_type); @@ -1349,6 +1353,9 @@ END return 1; } +############################################ +## csv output routines ## +############################################ sub outsheet_csv { my ($sheet,$r) = @_; my $csvdata = ''; @@ -1370,26 +1377,183 @@ sub outsheet_csv { @Values = (); } # - $r->print('
'.$csvdata."\n
"); + # Write the CSV data to a file and serve up a link + # + my $filename = '/prtspool/'. + $ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'. + time.'_'.rand(1000000000).'.csv'; + my $file; + unless ($file = Apache::File->new('>'.'/home/httpd'.$filename)) { + $r->log_error("Couldn't open $filename for output $!"); + $r->print("Problems occured in writing the csv file. ". + "This error has been logged. ". + "Please alert your LON-CAPA administrator."); + $r->print("
\n".$csvdata."
\n"); + return 0; + } + print $file $csvdata; + close($file); + $r->print('

'. + 'Your CSV spreadsheet.'."\n"); + # + return 1; +} + +############################################ +## Excel output routines ## +############################################ +sub outsheet_recursive_excel { + my ($sheet,$r) = @_; + return undef if ($sheet->{'sheettype'} ne 'classcalc'); + my ($workbook,$filename) = &create_excel_spreadsheet($sheet,$r); + return undef if (! defined($workbook)); + # + # Create main worksheet + my $main_worksheet = $workbook->addworksheet('main'); + # + # Figure out who the students are + my %f=&getformulas($sheet); + my $count = 0; + $r->print("
\n"); + $r->rflush(); + foreach (keys(%f)) { + next if ($_!~/^A(\d+)/ || $1 == 0 || ($f{$_}=~/^[!~-]/)); + $count++; + my ($sname,$sdom) = split(':',$f{$_}); + my $student_excel_worksheet=$workbook->addworksheet($sname.'@'.$sdom); + # Create a new spreadsheet + my $studentsheet = &makenewsheet($sname,$sdom,'studentcalc',undef); + # Read in the spreadsheet definition + &readsheet($studentsheet,'default_studentcalc'); + # Determine the structure (contained assessments, etc) of the sheet + &updatesheet($studentsheet); + # Load in the (possibly cached) data from the assessment sheets + &loadrows($studentsheet); + # Compute the sheet + &calcsheet($studentsheet); + &Apache::lonnet::logthis("Sheet value for A0 = ".$sheet->{'values'}->{'A0'}); + # Stuff the sheet into excel + &export_sheet_as_excel($studentsheet,$student_excel_worksheet); + if ($count % 5 == 0) { + $r->print($count.' students completed
'); + $r->rflush(); + } + } + # + $r->print('All students spreadsheets completed
'); + $r->rflush(); + # + # &export_sheet_as_excel fills $worksheet with the data from $sheet + &export_sheet_as_excel($sheet,$main_worksheet); # + $workbook->close(); + # Okay, the spreadsheet is taken care of, so give the user a link. + $r->print('

'. + 'Your Excel spreadsheet.'."\n"); return 1; } sub outsheet_excel { my ($sheet,$r) = @_; + my ($workbook,$filename) = &create_excel_spreadsheet($sheet,$r); + return undef if (! defined($workbook)); + my $sheetname; + if ($sheet->{'sheettype'} eq 'classcalc') { + $sheetname = 'Main'; + } elsif ($sheet->{'sheettype'} eq 'studentcalc') { + $sheetname = $sheet->{'uname'}.'@'.$sheet->{'udom'}; + } elsif ($sheet->{'sheettype'} eq 'assesscalc') { + $sheetname = $sheet->{'uname'}.'@'.$sheet->{'udom'}.' assessment'; + } + my $worksheet = $workbook->addworksheet($sheetname); + # + # &export_sheet_as_excel fills $worksheet with the data from $sheet + &export_sheet_as_excel($sheet,$worksheet); + # + $workbook->close(); + # Okay, the spreadsheet is taken care of, so give the user a link. + $r->print('

'. + 'Your Excel spreadsheet.'."\n"); + return 1; +} + +sub create_excel_spreadsheet { + my ($sheet,$r) = @_; + my $filename = '/prtspool/'. + $ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'. + time.'_'.rand(1000000000).'.xls'; + #&Apache::lonnet::logthis("spreadsheet:filename = ".$filename); + my $workbook = Spreadsheet::WriteExcel->new('/home/httpd'.$filename); + if (! defined($workbook)) { + $r->log_error("Error creating excel spreadsheet $filename: $!"); + $r->print("Problems creating new Excel file. ". + "This error has been logged. ". + "Please alert your LON-CAPA administrator"); + return undef; + } + # + # The spreadsheet stores temporary data in files, then put them + # together. If needed we should be able to disable this (memory only). + # The temporary directory must be specified before calling 'addworksheet'. + # File::Temp is used to determine the temporary directory. + $workbook->set_tempdir('/home/httpd/perl/tmp'); + # + # Determine the name to give the worksheet + return ($workbook,$filename); } +sub export_sheet_as_excel { + my $sheet = shift; + my $worksheet = shift; + #################################### + # Prepare to output rows + #################################### + my @Rows = &sort_indicies($sheet); + # + # Loop through the rows and output them one at a time + my $rows_output=0; + foreach my $rownum (@Rows) { + my ($rowlabel,@rowdata) = &get_row($sheet,$rownum); + my $cols_output = 0; + my $label = &format_excel_rowlabel($rowlabel); + $worksheet->write($rows_output,$cols_output++,$label); + if (ref($label)) { + $cols_output = (scalar(@$label)); + } + foreach my $cell (@rowdata) { + $worksheet->write($rows_output,$cols_output++, + $cell->{'value'}); + } + $rows_output++; + } + return; +} + +############################################ +## XML output routines ## +############################################ sub outsheet_xml { my ($sheet,$r) = @_; + ## Someday XML + ## Will be rendered for the user + ## But not on this day } +## +## Outsheet - calls other outsheet_* functions +## sub outsheet { my ($r,$sheet)=@_; - if (exists($ENV{'form.showcsv'})) { + if (! exists($ENV{'form.output'})) { + $ENV{'form.output'} = 'HTML'; + } + if (lc($ENV{'form.output'}) eq 'csv') { &outsheet_csv($sheet,$r); -# } elsif (exists($ENV{'form.excel'})) { -# &outsheet_excel($sheet,$r); -# } elsif (exists($ENV{'form.xml'})) { + } elsif (lc($ENV{'form.output'}) eq 'excel') { + &outsheet_excel($sheet,$r); + } elsif (lc($ENV{'form.output'}) eq 'recursive excel') { + &outsheet_recursive_excel($sheet,$r); +# } elsif (lc($ENV{'form.output'}) eq 'xml' ) { # &outsheet_xml($sheet,$r); } else { &outsheet_html($sheet,$r); @@ -1533,6 +1697,8 @@ sub makenewsheet { $sheet->{'cnum'} = $ENV{'course.'.$ENV{'request.course.id'}.'.num'}; $sheet->{'cdom'} = $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}; $sheet->{'chome'} = $ENV{'course.'.$ENV{'request.course.id'}.'.home'}; + $sheet->{'coursedesc'} = $ENV{'course.'.$ENV{'request.course.id'}. + 'description'}; $sheet->{'uhome'} = &Apache::lonnet::homeserver($uname,$udom); # # @@ -1776,7 +1942,7 @@ sub format_csv_rowlabel { return '"'.$result.'"'; } -sub format_plain_rowlabel { +sub format_excel_rowlabel { my $rowlabel = shift; return '' if ($rowlabel eq ''); my ($type,$labeldata) = split(':',$rowlabel,2); @@ -1787,8 +1953,10 @@ sub format_plain_rowlabel { $result = $title; } elsif ($type eq 'student') { my ($sname,$sdom,$fullname,$section,$id) = split(':',$labeldata); - $result = '"'. - join('","',($sname,$sdom,$fullname,$section,$id).'"'); + $section = '' if (! defined($section)); + $id = '' if (! defined($id)); + my @Data = ($sname,$sdom,$fullname,$section,$id); + $result = \@Data; } elsif ($type eq 'parameter') { $labeldata =~ s/
/ /g; $result = $labeldata; @@ -1992,7 +2160,7 @@ sub updatestudentassesssheet { # ------------------------------------------------ Load data for one assessment -sub loadstudent { +sub loadstudent{ my ($sheet)=@_; my %c=(); my %f=&getformulas($sheet); @@ -2044,8 +2212,10 @@ sub loadstudent { # sub loadcourse { my ($sheet,$r)=@_; + # my %c=(); my %f=&getformulas($sheet); + # my $total=0; foreach (keys(%f)) { if ($_=~/^A(\d+)/) { @@ -2368,7 +2538,7 @@ sub exportsheet { } # # Not cached - # + # my ($newsheet)=&makenewsheet($uname,$udom,$stype,$usymb); &readsheet($newsheet,$fn); &updatesheet($newsheet); @@ -2497,9 +2667,16 @@ sub cachedssheets { sub handler { my $r=shift; + my ($sheettype) = ($r->uri=~/\/(\w+)$/); + if (! exists($ENV{'form.Status'})) { $ENV{'form.Status'} = 'Active'; } + if ( ! exists($ENV{'form.output'}) || + ($sheettype ne 'classcalc' && + lc($ENV{'form.output'}) eq 'recursive excel')) { + $ENV{'form.output'} = 'HTML'; + } # Check this server my $loaderror=&Apache::lonnet::overloaderror($r); if ($loaderror) { return $loaderror; } @@ -2603,8 +2780,7 @@ ENDSCRIPT undef %updatedata; } # Read new sheet or modified worksheet - $r->uri=~/\/(\w+)$/; - my ($sheet)=&makenewsheet($aname,$adom,$1,$ENV{'form.usymb'}); + my ($sheet)=&makenewsheet($aname,$adom,$sheettype,$ENV{'form.usymb'}); # # If a new formula had been entered, go from work copy if ($ENV{'form.unewfield'}) { @@ -2753,10 +2929,24 @@ ENDSCRIPT $r->print('>'); # # CSV format checkbox (classcalc sheets only) - $r->print(' Output CSV format: print(' checked') if ($ENV{'form.showcsv'}); - $r->print('>'); + $r->print(' Output as \n"); + # if ($sheet->{'sheettype'} eq 'classcalc') { $r->print(' Student Status: '. &Apache::lonhtmlcommon::StatusOptions @@ -2764,13 +2954,13 @@ ENDSCRIPT } # # Buttons to insert rows - $r->print(< - -
-ENDINSERTBUTTONS +# $r->print(< +# +#
+#ENDINSERTBUTTONS # Print out sheet &outsheet($r,$sheet); $r->print('');