--- loncom/interface/Attic/lonspreadsheet.pm	2002/11/12 22:44:28	1.139
+++ loncom/interface/Attic/lonspreadsheet.pm	2002/11/21 19:50:49	1.148
@@ -1,5 +1,5 @@
 #
-# $Id: lonspreadsheet.pm,v 1.139 2002/11/12 22:44:28 matthew Exp $
+# $Id: lonspreadsheet.pm,v 1.148 2002/11/21 19:50:49 matthew Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -53,16 +53,16 @@ built-in functions.
 package Apache::lonspreadsheet;
             
 use strict;
+use Apache::Constants qw(:common :http);
+use Apache::lonnet;
+use Apache::lonhtmlcommon;
+use Apache::loncoursedata;
+use Apache::File();
 use Safe;
 use Safe::Hole;
 use Opcode;
-use Apache::lonnet;
-use Apache::Constants qw(:common :http);
 use GDBM_File;
 use HTML::TokeParser;
-use Apache::lonhtmlcommon;
-use Apache::loncoursedata;
-use Apache::File();
 use Spreadsheet::WriteExcel;
 
 #
@@ -1149,7 +1149,7 @@ sub exportdata {
 
 
 sub update_student_sheet{
-    my $sheet = shift;
+    my ($sheet,$r,$c) = @_;
     # Load in the studentcalc sheet
     &readsheet($sheet,'default_studentcalc');
     # Determine the structure (contained assessments, etc) of the sheet
@@ -1157,7 +1157,7 @@ sub update_student_sheet{
     # Load in the cached sheets for this student
     &cachedssheets($sheet);
     # Load in the (possibly cached) data from the assessment sheets        
-    &loadstudent($sheet);
+    &loadstudent($sheet,$r,$c);
     # Compute the sheet
     &calcsheet($sheet);
 }
@@ -1186,17 +1186,45 @@ sub get_row {
 ########################################################################
 sub sort_indicies {
     my $sheet = shift;
-    #
-    # Sort the rows in some manner
-    #
-    my @sortby=();
     my @sortidx=();
-    # Skip row 0
-    for (my $row=1;$row<=$sheet->{'maxrow'};$row++) {
-        push (@sortby, $sheet->{'safe'}->reval('$f{"A'.$row.'"}'));
-        push (@sortidx, $row);
+    #
+    if ($sheet->{'sheettype'} eq 'classcalc') {
+        my @sortby=(undef);
+        # Skip row 0
+        for (my $row=1;$row<=$sheet->{'maxrow'};$row++) {
+            my (undef,$sname,$sdom,$fullname,$section,$id) = 
+                split(':',$sheet->{'rowlabel'}->{$sheet->{'f'}->{'A'.$row}});
+            push (@sortby, lc($fullname));
+            push (@sortidx, $row);
+        }
+        @sortidx = sort { $sortby[$a] cmp $sortby[$b]; } @sortidx;
+    } elsif ($sheet->{'sheettype'} eq 'studentcalc') {
+        my @sortby1=(undef);
+        my @sortby2=(undef);
+        # Skip row 0
+        for (my $row=1;$row<=$sheet->{'maxrow'};$row++) {
+            my (undef,$symb,$uname,$udom,$mapid,$resid,$title) = 
+                split(':',$sheet->{'rowlabel'}->{$sheet->{'f'}->{'A'.$row}});
+            $symb = &Apache::lonnet::unescape($symb);
+            my ($sequence) = ($symb =~ /\/([^\/]*\.sequence)/);
+            if ($sequence eq '') {
+                $sequence = $symb;
+            }
+            push (@sortby1, $sequence);
+            push (@sortby2, $title);
+            push (@sortidx, $row);
+        }
+        @sortidx = sort { $sortby1[$a] cmp $sortby1[$b] || 
+                              $sortby2[$a] cmp $sortby2[$b] } @sortidx;
+    } else {
+        my @sortby=(undef);
+        # Skip row 0
+        for (my $row=1;$row<=$sheet->{'maxrow'};$row++) {
+            push (@sortby, $sheet->{'safe'}->reval('$f{"A'.$row.'"}'));
+            push (@sortidx, $row);
+        }
+        @sortidx = sort { $sortby[$a] cmp $sortby[$b]; } @sortidx;
     }
-    @sortidx=sort { lc($sortby[$a]) cmp lc($sortby[$b]); } @sortidx;
     return @sortidx;
 }
 
@@ -1332,6 +1360,20 @@ END
     foreach my $rownum (@Rows) {
         my ($rowlabel,@rowdata) = &get_row($sheet,$rownum);
         next if ($rowlabel =~ /^\s*$/);
+        next if (($sheet->{'sheettype'} eq 'assesscalc') && 
+                 (! $ENV{'form.showall'})                &&
+                 ($rowdata[0]->{'value'} =~ /^\s*$/));
+        if (! $ENV{'form.showall'} &&
+            $sheet->{'sheettype'} =~ /^(studentcalc|classcalc)$/) {
+            my $row_is_empty = 1;
+            foreach my $cell (@rowdata) {
+                if ($cell->{'value'} !~  /^\s*$/) {
+                    $row_is_empty = 0;
+                    last;
+                }
+            }
+            next if ($row_is_empty);
+        }
         #
         my $defaultbg='#E0FF';
         #
@@ -1488,15 +1530,14 @@ A link to the spreadsheet will be availa
 END
     $r->rflush();
     my $starttime = time;
-    foreach (keys(%f)) {
-	next if ($_!~/^A(\d+)/ || $1 == 0 || ($f{$_}=~/^[!~-]/));
+    foreach my $rownum (&sort_indicies($sheet)) {
         $count++;
-        my ($sname,$sdom) = split(':',$f{$_});
+        my ($sname,$sdom) = split(':',$f{'A'.$rownum});
         my $student_excel_worksheet=$workbook->addworksheet($sname.'@'.$sdom);
         # Create a new spreadsheet
         my $studentsheet = &makenewsheet($sname,$sdom,'studentcalc',undef);
         # Read in the spreadsheet definition
-        &update_student_sheet($studentsheet);
+        &update_student_sheet($studentsheet,$r,$c);
         # Stuff the sheet into excel
         &export_sheet_as_excel($studentsheet,$student_excel_worksheet);
         my $totaltime = int((time - $starttime) / $count * $sheet->{'maxrow'});
@@ -1612,9 +1653,20 @@ sub export_sheet_as_excel {
     # Loop through the rows and output them one at a time
     foreach my $rownum (@Rows) {
         my ($rowlabel,@rowdata) = &get_row($sheet,$rownum);
-        next if ($rowlabel =~ /^\s*$/);
+        next if ($rowlabel =~ /^[\s]*$/);
         $cols_output = 0;
         my $label = &format_excel_rowlabel($rowlabel);
+        if ( ! $ENV{'form.showall'} &&
+             $sheet->{'sheettype'} =~ /^(studentcalc|classcalc)$/) {
+            my $row_is_empty = 1;
+            foreach my $cell (@rowdata) {
+                if ($cell->{'value'} !~  /^\s*$/) {
+                    $row_is_empty = 0;
+                    last;
+                }
+            }
+            next if ($row_is_empty);
+        }
         $worksheet->write($rows_output,$cols_output++,$label);
         if (ref($label)) {
             $cols_output = (scalar(@$label));
@@ -1641,7 +1693,7 @@ sub outsheet_xml   {
 ## Outsheet - calls other outsheet_* functions
 ##
 sub outsheet {
-    my ($r,$sheet)=@_;
+    my ($sheet,$r)=@_;
     if (! exists($ENV{'form.output'})) {
         $ENV{'form.output'} = 'HTML';
     }
@@ -1753,7 +1805,8 @@ sub readsheet {
             if ($fh=Apache::File->new($includedir.'/'.$dfn)) {
                 $sheetxml=join('',<$fh>);
             } else {
-                $sheetxml='<field row="0" col="A">"Error"</field>';
+                # $sheetxml='<field row="0" col="A">"Error"</field>';
+                $sheetxml='<field row="0" col="A"></field>';
             }
             %f=%{&parse_sheet(\$sheetxml)};
         } elsif($fn=~/\/*\.spreadsheet$/) {
@@ -2011,6 +2064,9 @@ sub format_html_rowlabel {
                 '&mapid='.$mapid.'&resid='.$resid.'">'.$title.'</a>';
     } elsif ($type eq 'student') {
         my ($sname,$sdom,$fullname,$section,$id) = split(':',$labeldata);
+        if ($fullname =~ /^\s*$/) {
+            $fullname = $sname.'@'.$sdom;
+        }
         $result ='<a href="/adm/studentcalc?uname='.$sname.
             '&udom='.$sdom.'">';
         $result.=$section.'&nbsp;'.$id."&nbsp;".$fullname.'</a>';
@@ -2263,7 +2319,8 @@ sub updatestudentassesssheet {
     $sheet->{'maxrow'} = 0;
     my %existing=();
     # Now obsolete rows
-    while (my ($cell, $formula) = each (%f)) {
+    foreach my $cell (keys(%f)) {
+        my $formula = $f{$cell};
         next if ($cell !~ /^A(\d+)/);
         $sheet->{'maxrow'} = $1 if ($1 > $sheet->{'maxrow'});
         my ($usy,$ufn)=split(/__&&&\__/,$formula);
@@ -2296,9 +2353,9 @@ sub updatestudentassesssheet {
 # ------------------------------------------------ Load data for one assessment
 
 sub loadstudent{
-    my ($sheet)=@_;
-    my %c=();
-    my %f=&getformulas($sheet);
+    my ($sheet,$r,$c)=@_;
+    my %constants=();
+    my %formulas=&getformulas($sheet);
     $cachedassess=$sheet->{'uname'}.':'.$sheet->{'udom'};
     # Get ALL the student preformance data
     my @tmp = &Apache::lonnet::dump($sheet->{'cid'},
@@ -2311,50 +2368,51 @@ sub loadstudent{
     undef @tmp;
     # 
     my @assessdata=();
-    while (my ($cell,$value) = each (%f)) {
+    foreach my $cell (keys(%formulas)) {
+        my $value = $formulas{$cell};
+        if(defined($c) && ($c->aborted())) {
+            last;
+        }
 	next if ($cell !~ /^A(\d+)/);
         my $row=$1;
         next if (($value =~ /^[!~-]/) || ($row==0));
         my ($usy,$ufn)=split(/__&&&\__/,$value);
         @assessdata=&exportsheet($sheet,$sheet->{'uname'},
                                  $sheet->{'udom'},
-                                 'assesscalc',$usy,$ufn);
+                                 'assesscalc',$usy,$ufn,$r);
         my $index=0;
-        foreach ('A','B','C','D','E','F','G','H','I','J','K','L','M',
-                 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z') {
+        foreach my $col ('A','B','C','D','E','F','G','H','I','J','K','L','M',
+                         'N','O','P','Q','R','S','T','U','V','W','X','Y','Z') {
             if (defined($assessdata[$index])) {
-                my $col=$_;
                 if ($assessdata[$index]=~/\D/) {
-                    $c{$col.$row}="'".$assessdata[$index]."'";
+                    $constants{$col.$row}="'".$assessdata[$index]."'";
                 } else {
-                    $c{$col.$row}=$assessdata[$index];
-                }
-                unless ($col eq 'A') { 
-                    $f{$col.$row}='import';
+                    $constants{$col.$row}=$assessdata[$index];
                 }
+                $formulas{$col.$row}='import' if ($col ne 'A');
             }
             $index++;
         }
     }
     $cachedassess='';
     undef %cachedstores;
-    $sheet->{'f'} = \%f;
+    $sheet->{'f'} = \%formulas;
     &setformulas($sheet);
-    &setconstants($sheet,\%c);
+    &setconstants($sheet,\%constants);
 }
 
 # --------------------------------------------------- Load data for one student
 #
 sub loadcourse {
-    my ($sheet,$r)=@_;
+    my ($sheet,$r,$c)=@_;
     #
-    my %c=();
-    my %f=&getformulas($sheet);
+    my %constants=();
+    my %formulas=&getformulas($sheet);
     #
     my $total=0;
-    foreach (keys(%f)) {
+    foreach (keys(%formulas)) {
 	if ($_=~/^A(\d+)/) {
-	    unless ($f{$_}=~/^[\!\~\-]/) { $total++; }
+	    unless ($formulas{$_}=~/^[\!\~\-]/) { $total++; }
         }
     }
     my $now=0;
@@ -2371,12 +2429,16 @@ sub loadcourse {
 </script>
 ENDPOP
     $r->rflush();
-    foreach (keys(%f)) {
+    foreach (keys(%formulas)) {
+        if(defined($c) && ($c->aborted())) {
+            last;
+        }
 	next if ($_!~/^A(\d+)/);
         my $row=$1;
-        next if (($f{$_}=~/^[\!\~\-]/)  || ($row==0));
-        my ($sname,$sdom) = split(':',$f{$_});
-        my @studentdata=&exportsheet($sheet,$sname,$sdom,'studentcalc');
+        next if (($formulas{$_}=~/^[\!\~\-]/)  || ($row==0));
+        my ($sname,$sdom) = split(':',$formulas{$_});
+        my @studentdata=&exportsheet($sheet,$sname,$sdom,'studentcalc',
+                                     undef,undef,$r);
         undef %userrdatas;
         $now++;
         $r->print('<script>popwin.document.popremain.remaining.value="'.
@@ -2390,20 +2452,20 @@ ENDPOP
             if (defined($studentdata[$index])) {
                 my $col=$_;
                 if ($studentdata[$index]=~/\D/) {
-                    $c{$col.$row}="'".$studentdata[$index]."'";
+                    $constants{$col.$row}="'".$studentdata[$index]."'";
                 } else {
-                    $c{$col.$row}=$studentdata[$index];
+                    $constants{$col.$row}=$studentdata[$index];
                 }
                 unless ($col eq 'A') { 
-                    $f{$col.$row}='import';
+                    $formulas{$col.$row}='import';
                 }
             } 
             $index++;
         }
     }
-    $sheet->{'f'}=\%f;
+    $sheet->{'f'}=\%formulas;
     &setformulas($sheet);
-    &setconstants($sheet,\%c);
+    &setconstants($sheet,\%constants);
     $r->print('<script>popwin.close()</script>');
     $r->rflush(); 
 }
@@ -2411,7 +2473,7 @@ ENDPOP
 # ------------------------------------------------ Load data for one assessment
 #
 sub loadassessment {
-    my ($sheet)=@_;
+    my ($sheet,$r,$c)=@_;
 
     my $uhome = $sheet->{'uhome'};
     my $uname = $sheet->{'uname'};
@@ -2575,13 +2637,14 @@ sub updatesheet {
 
 sub loadrows {
     my ($sheet,$r)=@_;
+    my $c = $r->connection;
     my $stype=$sheet->{'sheettype'};
     if ($stype eq 'classcalc') {
-	&loadcourse($sheet,$r);
+	&loadcourse($sheet,$r,$c);
     } elsif ($stype eq 'studentcalc') {
-        &loadstudent($sheet);
+        &loadstudent($sheet,$r,$c);
     } else {
-        &loadassessment($sheet);
+        &loadassessment($sheet,$r,$c);
     }
 }
 
@@ -2589,7 +2652,11 @@ sub loadrows {
 
 sub checkthis {
     my ($keyname,$time)=@_;
-    return ($time<$expiredates{$keyname});
+    if (! exists($expiredates{$keyname})) {
+        return 0;
+    } else {
+        return ($time<$expiredates{$keyname});
+    }
 }
 
 sub forcedrecalc {
@@ -2622,7 +2689,8 @@ sub forcedrecalc {
 # returns the export row for a spreadsheet.
 #
 sub exportsheet {
-    my ($sheet,$uname,$udom,$stype,$usymb,$fn)=@_;
+    my ($sheet,$uname,$udom,$stype,$usymb,$fn,$r)=@_;
+    my $flag = 0;
     $uname = $uname || $sheet->{'uname'};
     $udom  = $udom  || $sheet->{'udom'};
     $stype = $stype || $sheet->{'sheettype'};
@@ -2676,7 +2744,7 @@ sub exportsheet {
     my ($newsheet)=&makenewsheet($uname,$udom,$stype,$usymb);
     &readsheet($newsheet,$fn);
     &updatesheet($newsheet);
-    &loadrows($newsheet);
+    &loadrows($newsheet,$r);
     &calcsheet($newsheet); 
     @exportarr=&exportdata($newsheet);
     ##
@@ -2691,14 +2759,24 @@ sub exportsheet {
                                        [$key],
                                        $sheet->{'cdom'},$sheet->{'cnum'});
         if ($tmp[0]!~/^error/) {
-            %currentlystored = @tmp;
+            # We only got one key, so we will access it directly.
+            foreach (split('___&___',$tmp[1])) {
+                my ($key,$value) = split('___=___',$_);
+                $key = '' if (! defined($key));
+                $currentlystored{$key} = $value;
+            }
         }
     } else {
         my @tmp = &Apache::lonnet::get('nohist_calculatedsheets_'.
                                        $sheet->{'cid'},[$key],
                                        $sheet->{'udom'},$sheet->{'uname'});
         if ($tmp[0]!~/^error/) {
-            %currentlystored = @tmp;
+            # We only got one key, so we will access it directly.
+            foreach (split('___&___',$tmp[1])) {
+                my ($key,$value) = split('___=___',$_);
+                $key = '' if (! defined($key));
+                $currentlystored{$key} = $value;
+            }
         }
     }
     #
@@ -2717,17 +2795,19 @@ sub exportsheet {
     #
     # Store away the new value
     #
+    my $timekey = $key.'.time';
     if ($stype eq 'studentcalc') {
-        &Apache::lonnet::put('nohist_calculatedsheets',
-                             { $key => $newstore,
-                               $key.time => $now },
-                             $sheet->{'cdom'},$sheet->{'cnum'});
-    } else {
-        &Apache::lonnet::put('nohist_calculatedsheets_'.$sheet->{'cid'},
-                             { $key => $newstore,
-                               $key.time => $now },
-                             $sheet->{'udom'},
-                             $sheet->{'uname'})
+        my $result = &Apache::lonnet::put('nohist_calculatedsheets',
+                                          { $key     => $newstore,
+                                            $timekey => $now },
+                                          $sheet->{'cdom'},
+                                          $sheet->{'cnum'});
+    } else {
+        my $result = &Apache::lonnet::put('nohist_calculatedsheets_'.$sheet->{'cid'},
+                                          { $key     => $newstore,
+                                            $timekey => $now },
+                                          $sheet->{'udom'},
+                                          $sheet->{'uname'});
     }
     return @exportarr;
 }
@@ -2742,7 +2822,7 @@ sub load_spreadsheet_expirationdates {
     my @tmp = &Apache::lonnet::dump('nohist_expirationdates',
                                     $ENV{'course.'.$cid.'.domain'},
                                     $ENV{'course.'.$cid.'.num'});
-    if (lc($tmp[0])!~/^error/){
+    if (lc($tmp[0]) !~ /^error/){
         %expiredates = @tmp;
     }
 }
@@ -3107,10 +3187,10 @@ ENDSCRIPT
     # Write the modified worksheet
     $r->print('<b>Current sheet:</b> '.$sheet->{'filename'}.'</p>');
     &tmpwrite($sheet);
-    if ($sheet->{'sheettype'} eq 'studentcalc') {
+    if ($sheet->{'sheettype'} eq 'assesscalc') {
         $r->print('<p>Show rows with empty A column: ');
     } else {
-        $r->print('<p>>Show empty rows: ');
+        $r->print('<p>Show empty rows: ');
     }
     #
     $r->print(&hiddenfield('userselhidden','true').
@@ -3163,7 +3243,7 @@ ENDSCRIPT
 #value='Insert Row Bottom'><br>
 #ENDINSERTBUTTONS
     # Print out sheet
-    &outsheet($r,$sheet);
+    &outsheet($sheet,$r);
     $r->print('</form></body></html>');
     #  Done
     return OK;