--- loncom/interface/spreadsheet/Spreadsheet.pm	2004/02/24 17:02:04	1.35
+++ loncom/interface/spreadsheet/Spreadsheet.pm	2005/04/29 18:13:07	1.43
@@ -1,5 +1,5 @@
 #
-# $Id: Spreadsheet.pm,v 1.35 2004/02/24 17:02:04 albertel Exp $
+# $Id: Spreadsheet.pm,v 1.43 2005/04/29 18:13:07 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -86,6 +86,15 @@ sub new {
     my ($stype) = ($class =~ /Apache::(.*)$/);
     #
     my ($name,$domain,$filename,$usymb)=@_;
+    if (defined($usymb) && ref($usymb)) {
+        $usymb = $usymb->symb;
+    }
+    if (! defined($name) || $name eq '') {
+        $name = $env{'user.name'};
+    }
+    if (! defined($domain) || $domain eq '') {
+        $domain = $env{'user.domain'};
+    }
     #
     my $self = {
         name     => $name,
@@ -94,12 +103,12 @@ sub new {
         symb     => $usymb,
         errorlog => '',
         maxrow   => 0,
-        cid      => $ENV{'request.course.id'},
-        cnum     => $ENV{'course.'.$ENV{'request.course.id'}.'.num'},
-        cdom     => $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
-        chome    => $ENV{'course.'.$ENV{'request.course.id'}.'.home'},
-        coursedesc => $ENV{'course.'.$ENV{'request.course.id'}.'.description'},
-        coursefilename => $ENV{'request.course.fn'},
+        cid      => $env{'request.course.id'},
+        cnum     => $env{'course.'.$env{'request.course.id'}.'.num'},
+        cdom     => $env{'course.'.$env{'request.course.id'}.'.domain'},
+        chome    => $env{'course.'.$env{'request.course.id'}.'.home'},
+        coursedesc => $env{'course.'.$env{'request.course.id'}.'.description'},
+        coursefilename => $env{'request.course.fn'},
         #
         # Flags
         temporary => 0,  # true if this sheet has been modified but not saved
@@ -123,8 +132,8 @@ sub new {
     #
     # Load in the spreadsheet definition
     $self->filename($filename);
-    if (exists($ENV{'form.workcopy'}) && 
-        $self->{'type'} eq $ENV{'form.workcopy'}) {
+    if (exists($env{'form.workcopy'}) && 
+        $self->{'type'} eq $env{'form.workcopy'}) {
         $self->load_tmp();
     } else {
         $self->load();
@@ -151,8 +160,8 @@ sub filename {
             $newfilename !~ /\w/ || $newfilename eq '') {
             my $key = 'course.'.$self->{'cid'}.'.spreadsheet_default_'.
                 $self->{'type'};
-            if (exists($ENV{$key}) && $ENV{$key} ne '') {
-                $newfilename = $ENV{$key};
+            if (exists($env{$key}) && $env{$key} ne '') {
+                $newfilename = $env{$key};
             } else {
                 $newfilename = 'default_'.$self->{'type'};
             }
@@ -250,10 +259,10 @@ sub initialize_spreadsheet_package {
 
 sub load_spreadsheet_expirationdates {
     undef %expiredates;
-    my $cid=$ENV{'request.course.id'};
+    my $cid=$env{'request.course.id'};
     my @tmp = &Apache::lonnet::dump('nohist_expirationdates',
-                                    $ENV{'course.'.$cid.'.domain'},
-                                    $ENV{'course.'.$cid.'.num'});
+                                    $env{'course.'.$cid.'.domain'},
+                                    $env{'course.'.$cid.'.num'});
     if (lc($tmp[0]) !~ /^error/){
         %expiredates = @tmp;
     }
@@ -307,6 +316,9 @@ Returns the safe space required by a Spr
 
 sub initialize_safe_space {
   my $self = shift;
+  my $usection = &Apache::lonnet::getsection($self->{'domain'},
+                                             $self->{'name'},
+                                             $env{'request.course.id'});
   if (! defined($safeeval)) {
       $safeeval = new Safe(shift);
       my $safehole = new Safe::Hole;
@@ -314,7 +326,7 @@ sub initialize_safe_space {
       $safeeval->permit(":base_math");
       $safeeval->permit("sort");
       $safeeval->deny(":base_io");
-      $safehole->wrap(\&Apache::lonnet::EXT,$safeeval,'&EXT');
+      $safehole->wrap(\&Apache::lonnet::EXT,$safeeval,'&Apache::lonnet::EXT');
       $safehole->wrap(\&mask,$safeeval,'&mask');
       $safeeval->share('$@');
       my $code=<<'ENDDEFS';
@@ -373,6 +385,25 @@ $errormsg = '';
 
 =pod
 
+=item EXT(parameter)
+
+Calls the system EXT function to determine the value of the given parameter.
+
+=cut
+
+#-------------------------------------------------------
+sub EXT {
+    my ($parameter) = @_;
+    return '' if (! defined($parameter) || $parameter eq '');
+    $parameter =~ s/^parameter\./resource\./;
+    my $value = &Apache::lonnet::EXT($parameter,$symb,$domain,$name,$usection);
+    return $value;
+}
+
+#-------------------------------------------------------
+
+=pod
+
 =item NUM(range)
 
 returns the number of items in the range.
@@ -565,7 +596,7 @@ sub SUMMAX {
     foreach (grep eval("/$mask/"),keys(%sheet_values)) {
 	push (@inside,$sheet_values{$_});
     }
-    @inside=sort(@inside);
+    @inside=sort {$a <=> $b} (@inside);
     my $sum=0; my $i;
     for ($i=$#inside;(($i>$#inside-$num) && ($i>=0));$i--) { 
         $sum+=$inside[$i];
@@ -592,7 +623,7 @@ sub SUMMIN {
     foreach (grep eval("/$mask/"),keys(%sheet_values)) {
 	$inside[$#inside+1]=$sheet_values{$_};
     }
-    @inside=sort(@inside);
+    @inside=sort {$a <=> $b} (@inside);
     my $sum=0; my $i;
     for ($i=0;(($i<$num) && ($i<=$#inside));$i++) { 
         $sum+=$inside[$i];
@@ -690,10 +721,11 @@ ENDDEFS
     # Place some of the %$self  items into the safe space except the safe space
     # itself
     my $initstring = '';
-    foreach (qw/name domain type usymb cid csec coursefilename
+    foreach (qw/name domain type symb cid csec coursefilename
              cnum cdom chome uhome/) {
         $initstring.= qq{\$$_="$self->{$_}";};
     }
+    $initstring.=qq{\$usection="$usection";};
     $self->{'safe'}->reval($initstring);
     return $self;
 }
@@ -905,7 +937,8 @@ sub sett {
             $t{$cell}=~s/(^|[^\"\'])([A-Za-z]\d+)/$1\$sheet_values\{\'$2\'\}/g;
             $t{$cell}=~s/(^|[^\"\'])\[([^\]]+)\]/$1.$self->expandnamed($2)/ge;
         } elsif  ( $col  =~ /^[A-Z]$/  ) {
-            if ($formula !~ /^\!/ && exists($self->{'constants'}->{$cell})) {
+            if ($formula !~ /^\!/ && exists($self->{'constants'}->{$cell})
+		&& $self->{'constants'}->{$cell} ne '') {
                 my $data = $self->{'constants'}->{$cell};
                 $t{$cell} = $data;
             }
@@ -1190,7 +1223,7 @@ sub display {
     my ($r) = @_;
     my $outputmode = 'html';
     foreach ($self->output_options()) {
-        if ($ENV{'form.output_format'} eq $_->{'value'}) {
+        if ($env{'form.output_format'} eq $_->{'value'}) {
             $outputmode = $_->{'value'};
             last;
         }
@@ -1234,7 +1267,7 @@ sub html_export_row {
     my $self = shift();
     my ($color) = @_;
     $color = '#CCCCFF' if (! defined($color));
-    my $allowed = &Apache::lonnet::allowed('mgr',$ENV{'request.course.id'});
+    my $allowed = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
     my $row_html;
     my @rowdata = $self->get_row(0);
     foreach my $cell (@rowdata) {
@@ -1251,7 +1284,7 @@ sub html_export_row {
 
 sub html_template_row {
     my $self = shift();
-    my $allowed = &Apache::lonnet::allowed('mgr',$ENV{'request.course.id'});
+    my $allowed = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
     my ($num_uneditable,$importcolor) = @_;
     my $row_html;
     my @rowdata = $self->get_template_row();
@@ -1288,7 +1321,7 @@ sub html_editable_cell {
     } elsif ($value =~ /^\s*$/ ) {
         $value = '<font color="'.$bgcolor.'">#</font>';
     } else {
-        $value = &HTML::Entities::encode($value) if ($value !~/&nbsp;/);
+        $value = &HTML::Entities::encode($value,'<>&"') if ($value !~/&nbsp;/);
     }
     return $value if (! $allowed);
     #
@@ -1311,14 +1344,14 @@ sub html_editable_cell {
 sub html_uneditable_cell {
     my ($cell,$bgcolor) = @_;
     my $value = (defined($cell) ? $cell->{'value'} : '');
-    $value = &HTML::Entities::encode($value) if ($value !~/&nbsp;/);
+    $value = &HTML::Entities::encode($value,'<>&"') if ($value !~/&nbsp;/);
     return '&nbsp;'.$value.'&nbsp;';
 }
 
 sub html_row {
     my $self = shift();
     my ($num_uneditable,$row,$exportcolor,$importcolor) = @_;
-    my $allowed = &Apache::lonnet::allowed('mgr',$ENV{'request.course.id'});
+    my $allowed = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
     my @rowdata = $self->get_row($row);
     my $num_cols_output = 0;
     my $row_html;
@@ -1342,7 +1375,7 @@ sub html_row {
 
 sub html_header {
     my $self = shift;
-    return '' if (! $ENV{'request.role.adv'});
+    return '' if (! $env{'request.role.adv'});
     return "<table>\n".
         '<tr><th align="center">'.&mt('Output Format').'</th></tr>'."\n".
         '<tr><td>'.$self->output_selector()."</td></tr>\n".
@@ -1367,10 +1400,10 @@ sub output_selector {
     my $self = shift();
     my $output_selector = '<select name="output_format" size="3">'."\n";
     my $default = 'html';
-    if (exists($ENV{'form.output_format'})) {
-        $default = $ENV{'form.output_format'} 
+    if (exists($env{'form.output_format'})) {
+        $default = $env{'form.output_format'} 
     } else {
-        $ENV{'form.output_format'} = $default;
+        $env{'form.output_format'} = $default;
     }
     foreach  ($self->output_options()) {
         $output_selector.='<option value="'.$_->{'value'}.'"';
@@ -1401,31 +1434,6 @@ sub excel_output_row {
     return;
 }
 
-sub create_excel_spreadsheet {
-    my $self = shift;
-    my ($r) = @_;
-    my $filename = '/prtspool/'.
-        $ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'.
-        time.'_'.rand(1000000000).'.xls';
-    my $workbook  = Spreadsheet::WriteExcel->new('/home/httpd'.$filename);
-    if (! defined($workbook)) {
-        $r->log_error("Error creating excel spreadsheet $filename: $!");
-        $r->print(&mt("Problems creating new Excel file.  ".
-                  "This error has been logged.  ".
-                  "Please alert your LON-CAPA administrator"));
-        return undef;
-    }
-    #
-    # The excel 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);
-}
-
 #
 # This routine is just a stub 
 sub outsheet_htmlclasslist {
@@ -1446,8 +1454,8 @@ sub outsheet_excel {
     #
     $r->print("<h2>".&mt('Preparing Excel Spreadsheet')."</h2>");
     #
-    # Create excel worksheet
-    my ($workbook,$filename) = $self->create_excel_spreadsheet($r);
+    # Create excel workbook
+    my ($workbook,$filename,$format)=&Apache::loncommon::create_workbook($r);
     return if (! defined($workbook));
     #
     # Create main worksheet
@@ -1458,16 +1466,18 @@ sub outsheet_excel {
     # Write excel header
     foreach my $value ($self->get_title()) {
         $cols_output = 0;
-        $worksheet->write($rows_output++,$cols_output,$value);
+        $worksheet->write($rows_output++,$cols_output,$value,$format->{'h1'});
     }
     $rows_output++;    # skip a line
     #
     # Write summary/export row
     $cols_output = 0;
-    $self->excel_output_row($worksheet,0,$rows_output++,'Summary');
+    $self->excel_output_row($worksheet,0,$rows_output++,'Summary',
+                            $format->{'b'});
     $rows_output++;    # skip a line
     #
-    $self->excel_rows($connection,$worksheet,$cols_output,$rows_output);
+    $self->excel_rows($connection,$worksheet,$cols_output,$rows_output,
+                      $format);
     #
     #
     # Close the excel file
@@ -1495,7 +1505,7 @@ sub outsheet_csv   {
     #
     # Open the csv file
     my $filename = '/prtspool/'.
-        $ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'.
+        $env{'user.name'}.'_'.$env{'user.domain'}.'_'.
         time.'_'.rand(1000000000).'.csv';
     my $file;
     unless ($file = Apache::File->new('>'.'/home/httpd'.$filename)) {
@@ -1744,7 +1754,7 @@ sub save {
         my $reply = &Apache::lonnet::put($filename,\%f,$cdom,$cnum);
         return $reply if ($reply ne 'ok');
         $reply = &Apache::lonnet::put($stype.'_spreadsheets',
-                     {$filename => $ENV{'user.name'}.'@'.$ENV{'user.domain'}},
+                     {$filename => $env{'user.name'}.'@'.$env{'user.domain'}},
                                       $cdom,$cnum);
         return $reply if ($reply ne 'ok');
         if ($makedef) { 
@@ -1770,8 +1780,8 @@ sub save {
 
 sub save_tmp {
     my $self = shift;
-    my $filename=$ENV{'user.name'}.'_'.
-        $ENV{'user.domain'}.'_spreadsheet_'.$self->{'symb'}.'_'.
+    my $filename=$env{'user.name'}.'_'.
+        $env{'user.domain'}.'_spreadsheet_'.$self->{'symb'}.'_'.
            $self->{'filename'};
     $filename=~s/\W/\_/g;
     $filename=$Apache::lonnet::tmpdir.$filename.'.tmp';
@@ -1790,8 +1800,8 @@ sub save_tmp {
 
 sub load_tmp {
     my $self = shift;
-    my $filename=$ENV{'user.name'}.'_'.
-        $ENV{'user.domain'}.'_spreadsheet_'.$self->{'symb'}.'_'.
+    my $filename=$env{'user.name'}.'_'.
+        $env{'user.domain'}.'_spreadsheet_'.$self->{'symb'}.'_'.
             $self->{'filename'};
     $filename=~s/\W/\_/g;
     $filename=$Apache::lonnet::tmpdir.$filename.'.tmp';