--- loncom/interface/Attic/lonspreadsheet.pm 2002/10/30 15:07:20 1.131 +++ loncom/interface/Attic/lonspreadsheet.pm 2002/11/04 22:35:45 1.132 @@ -1,5 +1,5 @@ # -# $Id: lonspreadsheet.pm,v 1.131 2002/10/30 15:07:20 matthew Exp $ +# $Id: lonspreadsheet.pm,v 1.132 2002/11/04 22:35:45 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -122,6 +122,7 @@ my $tmpdir; ## sub mask { my ($lower,$upper)=@_; + $upper = $lower if (! defined($upper)); # my ($la,$ld) = ($lower=~/([A-Za-z]|\*)(\d+|\*)/); my ($ua,$ud) = ($upper=~/([A-Za-z]|\*)(\d+|\*)/); @@ -130,9 +131,8 @@ sub mask { my $num=''; # if (($la eq '*') || ($ua eq '*')) { - $alpha='[A-Za-z]'; + $alpha='[A-Za-z]'; } else { - if (($la=~/[A-Z]/) && ($ua=~/[A-Z]/) || ($la=~/[a-z]/) && ($ua=~/[a-z]/)) { $alpha='['.$la.'-'.$ua.']'; @@ -194,8 +194,6 @@ sub mask { return '^'.$alpha.$num."\$"; } - - sub initsheet { my $safeeval = new Safe(shift); my $safehole = new Safe::Hole; @@ -238,6 +236,7 @@ undef @os; # Holds the names of other s # the spreadsheets that are available for the assessment sheet. # Set by &setothersheets. &setothersheets is called by &handler. A # related subroutine is &othersheets. +#$errorlog = ''; $maxrow = 0; $sheettype = ''; @@ -591,7 +590,8 @@ compute the average of the items in the #------------------------------------------------------- sub MEAN { my $mask=mask(@_); - my $sum=0; my $num=0; + my $sum=0; + my $num=0; foreach (grep /$mask/,keys(%sheet_values)) { $sum+=$sheet_values{$_}; $num++; @@ -926,6 +926,7 @@ sub calc { while ($notfinished) { $notfinished=0; foreach (keys(%t)) { + #$errorlog .= "$_:".$t{$_}; my $old=$sheet_values{$_}; $sheet_values{$_}=eval $t{$_}; if ($@) { @@ -933,6 +934,7 @@ sub calc { return $_.': '.$@; } if ($sheet_values{$_} ne $old) { $notfinished=1; $lastcalc=$_; } + #$errorlog .= ":".$sheet_values{$_}."\n"; } $depth++; if ($depth>100) { @@ -950,54 +952,39 @@ ENDDEFS } # -# +# # sub templaterow { my $sheet = shift; my @cols=(); - $cols[0]='Template'; + my $rowlabel = 'Template'; 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', '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') { my $fm=$sheet->{'f'}->{'template_'.$_}; $fm=~s/[\'\"]/\&\#34;/g; - push(@cols,"'template_$_','$fm'".'___eq___'.$fm); + push(@cols,{ name => 'template_'.$_, + formula => $fm, + value => $fm }); } - return @cols; + return ($rowlabel,@cols); } - sub outrowassess { # $n is the current row number - my $sheet = shift; - my $n=shift; - my $csv = $ENV{'form.showcsv'}; + my ($sheet,$n) = @_; my @cols=(); + my $rowlabel=''; if ($n) { my ($usy,$ufn)=split(/__&&&\__/,$sheet->{'f'}->{'A'.$n}); - if ($sheet->{'rowlabel'}->{$usy}) { - $cols[0]=&format_rowlabel($sheet->{'rowlabel'}->{$usy}); - if (! $csv) { - $cols[0].='
'. - ''; + $rowlabel = ''; } } else { - $cols[0]='Export'; + $rowlabel = 'Export'; } 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', @@ -1005,19 +992,25 @@ sub outrowassess { 'n','o','p','q','r','s','t','u','v','w','x','y','z') { my $fm=$sheet->{'f'}->{$_.$n}; $fm=~s/[\'\"]/\&\#34;/g; - push(@cols,"'$_$n','$fm'".'___eq___'.$sheet->{'values'}->{$_.$n}); + push(@cols,{ name => $_.$n, + formula => $fm, + value => $sheet->{'values'}->{$_.$n}}); } - return @cols; + return ($rowlabel,@cols); } sub outrow { - my $sheet=shift; - my $n=shift; + my ($sheet,$n)=@_; my @cols=(); + my $rowlabel; if ($n) { - $cols[0]=&format_rowlabel($sheet->{'rowlabel'}->{$sheet->{'f'}->{'A'.$n}}); + $rowlabel = $sheet->{'rowlabel'}->{$sheet->{'f'}->{'A'.$n}}; } else { - $cols[0]='Export'; + if ($sheet->{'sheettype'} eq 'classcalc') { + $rowlabel = 'Summary'; + } else { + $rowlabel = 'Export'; + } } 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', @@ -1025,9 +1018,11 @@ sub outrow { 'n','o','p','q','r','s','t','u','v','w','x','y','z') { my $fm=$sheet->{'f'}->{$_.$n}; $fm=~s/[\'\"]/\&\#34;/g; - push(@cols,"'$_$n','$fm'".'___eq___'.$sheet->{'values'}->{$_.$n}); + push(@cols,{ name => $_.$n, + formula => $fm, + value => $sheet->{'values'}->{$_.$n}}); } - return @cols; + return ($rowlabel,@cols); } # ------------------------------------------------ Add or change formula values @@ -1083,6 +1078,11 @@ sub getformulas { return %{$sheet->{'safe'}->varglob('f')}; } +sub geterrorlog { + my $sheet = shift; + return ${$sheet->{'safe'}->varglob('errorlog')}; +} + # ----------------------------------------------------- Get value of $f{'A'.$n} sub getfa { my $sheet = shift; @@ -1113,176 +1113,273 @@ sub exportdata { # # --------------------------------------------- Produce output row n from sheet -sub rown { - my ($sheet,$n)=@_; - my $defaultbg; - my $rowdata=''; - my $dataflag=0; - unless ($n eq '-') { - $defaultbg=((($n-1)/5)==int(($n-1)/5))?'#E0E0':'#FFFF'; - } else { - $defaultbg='#E0FF'; - } - unless ($ENV{'form.showcsv'}) { - $rowdata.="\n$n"; - } else { - $rowdata.="\n".'"'.$n.'"'; - } - my $showf=0; - # - # Determine how many pink (uneditable) cells there are in this sheet. - my $maxred=1; - my $sheettype=$sheet->{'sheettype'}; - if ($sheettype eq 'studentcalc') { - $maxred=26; - } elsif ($sheettype eq 'assesscalc') { - $maxred=1; - } else { - $maxred=26; - } - $maxred=1 if (&getfa($sheet,$n)=~/^[\~\-]/); - # - # Get the proper row - my @rowdata; +sub get_row { + my ($sheet,$n) = @_; + my ($rowlabel,@rowdata); if ($n eq '-') { - @rowdata = &templaterow($sheet); - $n=-1; - $dataflag=1; - } elsif ($sheettype eq 'studentcalc') { - @rowdata = &outrowassess($sheet,$n); - } else { - @rowdata = &outrow($sheet,$n); - } - # - foreach (@rowdata) { - my $bgcolor=$defaultbg.((($showf-1)/5==int(($showf-1)/5))?'99':'DD'); - my ($fm,$vl)=split(/\_\_\_eq\_\_\_/,$_); - if ((($vl ne '') || ($vl eq '0')) && - (($showf==1) || ($sheettype ne 'studentcalc'))) { $dataflag=1; } - if ($showf==0) { $vl=$_; } - unless ($ENV{'form.showcsv'}) { - if ($showf<=$maxred) { $bgcolor='#FFDDDD'; } - if (($n==0) && ($showf<=26)) { $bgcolor='#CCCCFF'; } - if (($showf>$maxred) || ((!$n) && ($showf>0))) { - if ($vl eq '') { - $vl='#'; - } - $rowdata.=''; - if ($ENV{'request.role'} =~ /^st\./) { - $rowdata.=$vl; - } else { - $rowdata.=''. - $vl.''; - } - $rowdata.=''; - } else { - $rowdata.=' '.$vl.' '; - } - } else { - $rowdata.=',"'.$vl.'"'; - } - $showf++; - } # End of foreach($safeval...) - if ($ENV{'form.showall'} || ($dataflag)) { - return $rowdata.($ENV{'form.showcsv'}?'':''); + ($rowlabel,@rowdata) = &templaterow($sheet); + } elsif ($sheet->{'sheettype'} eq 'studentcalc') { + ($rowlabel,@rowdata) = &outrowassess($sheet,$n); } else { - return ''; + ($rowlabel,@rowdata) = &outrow($sheet,$n); } + return ($rowlabel,@rowdata); } -# ------------------------------------------------------------- Print out sheet - -sub outsheet { - my ($r,$sheet)=@_; - my $maxred = 26; # The maximum number of cells to show as - # red (uneditable) - # To make student sheets uneditable could we - # set $maxred = 52? - # - my $realm='Course'; # 'assessment', 'user', or 'course' sheet - if ($sheet->{'sheettype'} eq 'assesscalc') { - $maxred=1; - $realm='Assessment'; - } elsif ($sheet->{'sheettype'} eq 'studentcalc') { - $maxred=26; - $realm='User'; - } - # - # Column label - my $tabledata; - if ($ENV{'form.showcsv'}) { - $tabledata='
';
-    } else { 
-        $tabledata=''.
-                  ''.
-                  '';
-        my $showf=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',
-                 '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') {
-            $showf++;
-            if ($showf<=$maxred) { 
-                $tabledata.='";
-        }
-        $tabledata.=''.&rown($sheet,'-').
-            &rown($sheet,0);
-    }
-    $r->print($tabledata);
-    #
-    # Prepare to output rows
-    my $row;
+########################################################################
+########################################################################
+sub sort_indicies {
+    my $sheet = shift;
     #
     # Sort the rows in some manner
     #
     my @sortby=();
     my @sortidx=();
-    for ($row=1;$row<=$sheet->{'maxrow'};$row++) {
+    for (my $row=1;$row<=$sheet->{'maxrow'};$row++) {
         push (@sortby, $sheet->{'safe'}->reval('$f{"A'.$row.'"}'));
-        push (@sortidx, $row-1);
+        push (@sortidx, $row);
     }
     @sortidx=sort { lc($sortby[$a]) cmp lc($sortby[$b]); } @sortidx;
+    return @sortidx;
+}
+
+########################################################################
+########################################################################
+
+sub html_editable_cell {
+    my ($cell,$bgcolor) = @_;
+    my $result;
+#    if (defined($cell)) {
+#        &Apache::lonnet::logthis("cell ".$cell->{'name'}.
+#                                 " = ".$cell->{'value'}.
+#                                 " : ".$cell->{'formula'});
+#    }
+    my ($name,$formula,$value);
+    if (defined($cell)) {
+        $name    = $cell->{'name'};
+        $formula = $cell->{'formula'};
+        $value   = $cell->{'value'};
+    }
+    $name    = '' if (! defined($name));
+    $formula = '' if (! defined($formula));
+    if (! defined($value)) {
+        $value = '#';
+        if ($formula ne '') {
+            $value = 'undefined value';
+        }
+    }
     #
-    # Determine the type of child spreadsheets
-    my $what='Student';
+    $result .= ''.$value.'';
+    return $result;
+}
+
+sub html_uneditable_cell {
+    my ($cell,$bgcolor) = @_;
+    my $value = (defined($cell) ? $cell->{'value'} : '');
+    return ' '.$value.' ';
+}
+
+########################################################################
+########################################################################
+
+sub outsheet_html  {
+    my ($sheet,$r) = @_;
+    my ($num_uneditable,$realm,$row_type);
     if ($sheet->{'sheettype'} eq 'assesscalc') {
-        $what='Item';
+        $num_uneditable = 1;
+        $realm = 'Assessment';
+        $row_type = 'Item';
     } elsif ($sheet->{'sheettype'} eq 'studentcalc') {
-        $what='Assessment';
+        $num_uneditable = 26;
+        $realm = 'User';
+        $row_type = 'Assessment';
+    } elsif ($sheet->{'sheettype'} eq 'classcalc') {
+        $num_uneditable = 26;
+        $realm = 'Course';
+        $row_type = 'Student';
+    } else {
+        return;  # error
+    }
+    ####################################
+    # Print out header table
+    ####################################
+    my $num_left = 52-$num_uneditable;
+    my $tabledata =<<"END";
+
'. - ''.$realm.'ImportCalculations
'; - } else { - $tabledata.=''; - } - $tabledata.="$_
+ + + + + +END + my $label_num = 0; + foreach (split(//,'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz')){ + if ($label_num<$num_uneditable) { + $tabledata.='"; + $label_num++; } + $tabledata.="\n"; + $r->print($tabledata); + #################################### + # Print out template row + #################################### + my ($rowlabel,@rowdata) = &get_row($sheet,'-'); + my $row_html = ''; + my $num_cols_output = 0; + foreach my $cell (@rowdata) { + if ($num_cols_output++ < $num_uneditable) { + $row_html .= ''; + } + $row_html.= "\n"; + $r->print($row_html); + #################################### + # Print out summary/export row + #################################### + my ($rowlabel,@rowdata) = &get_row($sheet,'0'); + my $rowcount = 0; + $row_html = ''; + $num_cols_output = 0; + foreach my $cell (@rowdata) { + if ($num_cols_output++ < 26) { + $row_html .= ''; + } + $row_html.= "\n"; + $r->print($row_html); + $r->print('
$realm + Import + Calculations
'; + } else { + $tabledata.=''; + } + $tabledata.="$_
'.&format_rowlabel($rowlabel).''; + $row_html .= &html_uneditable_cell($cell,'#FFDDDD'); + } else { + $row_html .= ''; + $row_html .= &html_editable_cell($cell,'#E0FFDD'); + } + $row_html .= '
'.&format_rowlabel($rowlabel).''; + $row_html .= &html_editable_cell($cell,'#CCCCFF'); + } else { + $row_html .= ''; + $row_html .= &html_uneditable_cell(undef,'#CCCCFF'); + } + $row_html .= '
'); + #################################### + # Prepare to output rows + #################################### + my @Rows = &sort_indicies($sheet); # # Loop through the rows and output them one at a time - my $n=0; - for ($row=0;$row<$sheet->{'maxrow'};$row++) { - my $thisrow=&rown($sheet,$sortidx[$row]+1); - if ($thisrow) { - if (($n/25==int($n/25)) && (!$ENV{'form.showcsv'})) { + my $rows_output=0; + foreach my $rownum (@Rows) { + my ($rowlabel,@rowdata) = &get_row($sheet,$rownum); + # + my $defaultbg='#E0FF'; + # + my $row_html ="\n".''.$rownum. + ''; + # + if ($sheet->{'sheettype'} eq 'classcalc') { + $row_html.=''.&format_rowlabel($rowlabel).''; + # Output links for each student? + # Nope, that is already done for us in format_rowlabel (for now) + } elsif ($sheet->{'sheettype'} eq 'studentcalc') { + $row_html.=''.&format_rowlabel($rowlabel); + $row_html.= '
'. + ''; + } elsif ($sheet->{'sheettype'} eq 'assesscalc') { + $row_html.=''.&format_rowlabel($rowlabel).''; + } + # + my $shown_cells = 0; + foreach my $cell (@rowdata) { + my $value = $cell->{'value'}; + my $formula = $cell->{'formula'}; + my $cellname = $cell->{'name'}; + # + my $bgcolor; + if ($shown_cells && ($shown_cells/5 == int($shown_cells/5))) { + $bgcolor = $defaultbg.'99'; + } else { + $bgcolor = $defaultbg.'DD'; + } + $bgcolor='#FFDDDD' if ($shown_cells < $num_uneditable); + # + $row_html.=''; + if ($shown_cells < $num_uneditable) { + $row_html .= &html_uneditable_cell($cell,$bgcolor); + } else { + $row_html .= &html_editable_cell($cell,$bgcolor); + } + $row_html.=''; + $shown_cells++; + } + if ($row_html) { + if ($rows_output % 25 == 0) { $r->print("\n
\n"); $r->rflush(); - $r->print(''); - $r->print('
 '.$what.''. + $r->print(''. + ''. + '\n"); } - $n++; - $r->print($thisrow); + $rows_output++; + $r->print($row_html); } } - $r->print($ENV{'form.showcsv'}?'':'
 '.$row_type.''. join('', (split(//,'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. 'abcdefghijklmnopqrstuvwxyz'))). "
'); + # + $r->print('
'); + # + # Debugging code (be sure to uncomment errorlog code in safe space): + # + # $r->print("\n
");
+    # $r->print(&geterrorlog($sheet));
+    # $r->print("\n
"); + return 1; } -# -# ----------------------------------------------- Read list of available sheets -# +sub outsheet_csv { + my ($sheet,$r) = @_; +} + +sub outsheet_excel { + my ($sheet,$r) = @_; +} + +sub outsheet_xml { + my ($sheet,$r) = @_; +} + +sub outsheet { + my ($r,$sheet)=@_; + &outsheet_html($sheet,$r); +# if (exists($ENV{'form.csv'})) { +# &outsheet_csv($sheet,$r); +# } elsif (exists($ENV{'form.excel'})) { +# &outsheet_excel($sheet,$r); +# } elsif (exists($ENV{'form.xml'})) { +# &outsheet_xml($sheet,$r); +# } else { +# &outsheet_html($sheet,$r); +# } +} + +######################################################################## +######################################################################## sub othersheets { my ($sheet,$stype)=@_; $stype = $sheet->{'sheettype'} if (! defined($stype)); @@ -1300,7 +1397,6 @@ sub othersheets { return @alternatives; } - # # -------------------------------------- Parse a spreadsheet # @@ -1616,6 +1712,7 @@ sub parmval { sub format_rowlabel { my $rowlabel = shift; + return '' if ($rowlabel eq ''); my ($type,$labeldata) = split(':',$rowlabel,2); my $result = ''; if ($type eq 'symb') { @@ -1643,7 +1740,11 @@ sub format_rowlabel { } $result = $labeldata; } else { - &Apache::lonnet::logthis("lonspreadsheet:bogus rowlabel type: $type"); + if ($ENV{'form.showcsv'}) { + $result = $rowlabel; + } else { + $result = ''.$rowlabel.''; + } } return $result; } @@ -1932,7 +2033,7 @@ ENDPOP 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') { - if (defined($studentdata[$index++])) { + if (defined($studentdata[$index])) { my $col=$_; if ($studentdata[$index]=~/\D/) { $c{$col.$row}="'".$studentdata[$index]."'"; @@ -1942,7 +2043,8 @@ ENDPOP unless ($col eq 'A') { $f{$col.$row}='import'; } - } + } + $index++; } } $sheet->{'f'}=\%f; @@ -2172,7 +2274,8 @@ sub exportsheet { $udom = $udom || $sheet->{'udom'}; $stype = $stype || $sheet->{'sheettype'}; my @exportarr=(); - if (defined($usymb) && ($usymb=~/^\_(\w+)/) && (!$fn)) { + if (defined($usymb) && ($usymb=~/^\_(\w+)/) && + (!defined($fn) || $fn eq '')) { $fn='default_'.$1; } #