Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Sub call isn't returning values

by Lori713 (Pilgrim)
on Mar 02, 2004 at 17:56 UTC ( [id://333316]=perlquestion: print w/replies, xml ) Need Help??

Lori713 has asked for the wisdom of the Perl Monks concerning the following question:

I'll apologize up front for this being kind of long... I've edited it down to what I hope is clear and concise. I've created a package that contains some subroutines I use on a regular basis. The one I'm having trouble with (&call_vars) is not working in one instance and I can't figure out why.

When nc_period.pl (below) is called, it initially creates a web page, and &call_vars works nicely (just FYI... &call_vars works nicely on other pages). However, if the user clicks on the "Download to Excel" button on this page, nc_period.pl is called again, the mime Content type is changed, and &call_vars is called again.

The problem is that the variables within &call_vars come out blank/empty after the page is called that second time and outputted to Excel. I think my template is okay because I hard-coded the SQL and the data (numbers/dollars) show up in Excel; however, none of the other variables that I've got stored in hidden fields show up.

--Even if I hard-code one of the values I'm looking for within the if loop that determines if it's
   Excel, it doesn't get passed to Excel.
--I also tried something like $summ_descr = $CGI->param('cell_descr'); just to see if that would work, and it
   doesn't get passed down to the subsequent portions of the program (right now the SQL is
   hard-coded but these variables would actually fill in some of the hard-coded stuff).
--I confirmed that the hidden fields appear on the initial web page (viewed source) and they have
   the appropriate values, so &call_vars should have picked them up.
--I've tried removing the $|=1;.
--I tried changing the order of &call_vars and print $CGI->header; (or Excel's mime type), but no luck.
--I've also tried rearranging where &call_vars appears (in the loop, outside the loop).
--I have also triple-checked to make sure that the order of the hidden fields (and TMPL_INCLUDE
   where they're stashed) is in the exact order it needs to be to be split out correctly (it is, and
   I confirmed it because the &call_vars works correctly on all subsequent and previous pages.
--I was beginning to wonder if there's something about returning the &call_vars values to something
   inside a loop that makes it not work, but I put the &call_vars inside the web page's part of the loop
   and it works... so I'm not sure what I'm missing.

One last note: I have three pages that work consecutively and all have buttons to download to Excel. Code very similar to what's below works for the first page (both creating the initial web page and creating the download to Excel); it's just not working for this second page and I can't figure out why.

Does anybody see something I'm not? Thanks in advance for any clues you can give me.

nc_period.pl

#!/usr/local/bin/perl5_8 use strict; use nc_rpt_library; use HTML::Template; use DBI; use CGI ':standard'; my $CGI = CGI->new; $|=1; #Determine if this is download to Excel or web report. my $excel = $CGI->param('excel'); my ($template_name, $summ_row_nobr, $ouc_code_fix, $new_per_fytd ); if ( $excel eq "Download to Excel" ) { print $CGI->header(-type => 'application/vnd.ms-excel'); &call_vars; #calls in hidde +n fields $template_name = "nc_period_xl.tmpl"; } elsif ( $excel == "" ) { &call_vars; print $CGI->header; $template_name = "nc_period.tmpl"; $summ_descr = $CGI->param('cell_descr'); #these are coming +from $summ_col = $CGI->param('cell_col'); #the previous pa +ge and $summ_row = $CGI->param('cell_row'); #need to be capt +ured } my $template = HTML::Template->new( filename => $template_nam +e, associate => $CGI, loop_context_vars => 1, global_vars => 1, ); #Period drilldown SQL (hard-coded for now) --- snipped out (that par +t works) #Fetch Period cell data from database --- snipped out (that par +t works) #Create @loop_data array for HTML::Template --- snipped out (that par +t works) ###################################################################### +######### #NOTE: LOTS OF VARIABLES SNIPPED OUT HERE but they match the &call_ +vars list. #For the masochists among you, the entire code is posted on my notepad +. ###################################################################### +######### $template->param( title_bar => "Report $rpt_no - $rpt_lbl - Per +iod", rpt_no => $rpt_no, rpt_lbl => $rpt_lbl, rpt_asofdt => $rpt_asofdt, rpt_name => $rpt_name, project => $project, proj_ref => $proj_ref, attr_dept => $attr_dept, attr_descr => $attr_descr, attr_award => $attr_award, attr_prog => $attr_prog, attr_projpd => $attr_projpd, attr_fyr => $attr_fyr, attr_budgpd => $attr_budgpd, attr_fund => $attr_fund, attr_rate => $attr_rate, attr_sub => $attr_sub, attr_status => $attr_status, attr_spec => $attr_spec, attr_equip => $attr_equip, attr_resp => $attr_resp, attr_pi => $attr_pi, passdata => \@loop_data, ); print $template->output();
and the relevant part of my package:
package nc_rpt_library; #contains various subroutines used by the Campus Financial Reporting s +ystem use strict; use Exporter (); our @ISA = 'Exporter'; our @EXPORT; use vars @EXPORT=qw/ &call_vars &commify &dberror $CGI $spec_vars $titlebar $rpt_no $rpt_lbl $rpt_asofdt $rpt_name $project $proj_re +f $attr_dept $attr_descr $attr_award $attr_prog $attr_projpd $attr_f +yr $attr_budgpd $attr_fund $attr_rate $attr_sub $attr_status $attr_sp +ec $attr_equip $attr_resp $attr_pi $rpt_type $from_act_tbl $from_bud_ +tbl $per_crmo $per_fytd $per_fytdadj $per_fytdbal $per_fytdbaladj $att +r_pfyr $ledger $timespan $bud_led_amt $act_led_amt $pre_led_amt $enc_led_ +amt $cell_col $cell_row $acct_sql $src_or_scen $curr_or_stat $src_lbl +$summ_col $summ_row $per_col $per_row $jrnl_col $jrnl_row $ouc_code $proj_di +splay $cell_descr $summ_descr $mycheck $rpt_id $rpt_dates $sql_asofyr $s +ql_asofmo $sql_asofdy $amt_type $led_tbl /; sub call_vars #pulls in passed variables { use CGI ':standard'; my $CGI = CGI->new; my $spec_vars = param('spec_vars'); #strip out descr labels in front of actual value $spec_vars =~ s/(xxx\w*zzz)(.*|\n~)(.{1})/$2/gm; ( $titlebar, $rpt_no, $rpt_lbl, $rpt_asofdt, $rpt_name, $project, $pro +j_ref, $attr_dept, $attr_descr, $attr_award, $attr_prog, $attr_projpd, $a +ttr_fyr, $attr_budgpd, $attr_fund, $attr_rate, $attr_sub, $attr_status, $at +tr_spec, $attr_equip, $attr_resp, $attr_pi, $rpt_type, $from_act_tbl, $from +_bud_tbl, $per_crmo, $per_fytd, $per_fytdadj, $per_fytdbal, $per_fytdbaladj, + $attr_pfyr, $ledger, $timespan, $bud_led_amt, $act_led_amt, $pre_led_amt, $enc +_led_amt, $cell_col, $cell_row, $acct_sql, $src_or_scen, $curr_or_stat, $src +_lbl, $summ_col, $summ_row, $per_col, $per_row, $jrnl_col, $jrnl_row, $ouc_code, $p +roj_display, $cell_descr, $summ_descr, $mycheck, $rpt_id, $rpt_dates, $sql_asof +yr, $sql_asofmo, $sql_asofdy, $amt_type, $led_tbl, ) = split /~\s?/, $spec_vars; return; }

Lori

updateI did read the latest about that buffer clearing What does this mean? $!=1 but it doesn't seem to apply to me (but I understand it better now).

Replies are listed 'Best First'.
Re: Sub call isn't returning values
by chromatic (Archbishop) on Mar 02, 2004 at 19:52 UTC

    Did you realize that you're constructing two CGI objects? You only need one, especially as when you create the second one, you've already consumed all of the input.

    Further, you're mixing the procedural and the method calls in CGI. Choose one or the other.

    I suggest passing $CGI to call_vars and using that within the function.

      Thanks for helping me realize I had two CGI objects. I had misunderstood how CGI works with regard to objects (I was thinking each field was its own object).

      I knew I was not getting data the second time around, but I didn't understand why. I read (for the nth time) the CGI.pm docs (I have them printed out because I refer to them so often). I understand better now the differences between procedural and method, but it'll take some more studying to completely figure it out. I didn't see where I had mixed up my calls.

      I responded to merlyn's comments above and was able to get the code working by copying my hidden field line in my template's main form area to the button form area.

      Thanks again for your help!

      Lori

•Re: Sub call isn't returning values
by merlyn (Sage) on Mar 02, 2004 at 18:07 UTC
    use vars @EXPORT=qw/ &call_vars &commify &dberror $CGI $spec_vars $titlebar $rpt_no $rpt_lbl $rpt_asofdt $rpt_name $project $proj_re +f $attr_dept $attr_descr $attr_award $attr_prog $attr_projpd $attr_f +yr $attr_budgpd $attr_fund $attr_rate $attr_sub $attr_status $attr_sp +ec $attr_equip $attr_resp $attr_pi $rpt_type $from_act_tbl $from_bud_ +tbl $per_crmo $per_fytd $per_fytdadj $per_fytdbal $per_fytdbaladj $att +r_pfyr $ledger $timespan $bud_led_amt $act_led_amt $pre_led_amt $enc_led_ +amt $cell_col $cell_row $acct_sql $src_or_scen $curr_or_stat $src_lbl +$summ_col $summ_row $per_col $per_row $jrnl_col $jrnl_row $ouc_code $proj_di +splay $cell_descr $summ_descr $mycheck $rpt_id $rpt_dates $sql_asofyr $s +ql_asofmo $sql_asofdy $amt_type $led_tbl /;
    Without completely understanding the rest of your code, I would bet the rent money that this code will be difficult to (a) get working and (b) maintain.

    Why do you have so many variables, especially imported from what appears to be data? Are you actually using all the variables as control or summation in the rest of your program logic? If so, you should probably be modularizing your code instead of passing them back to the caller of this module as a big messy blob.

    More than likely, what you should be doing instead is exporting a single subroutine that returns a hash ref containing these values, and focussing the logic on treating these values as a bundle, not broken out into 87-gazillion named Perl variables.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

      Thank you for your suggestions. You are, without question, correct. This code is kludgy (at best). However, it does work in every instance but the one described. Given my deadline (which has passed, and testing is to begin with my customers on March 17th), it was the best I could come up with (as a beginner) and still make the boss happy.

      I did try to use CGI::Session but had difficulty in getting that to work (see previous posts). I've been told not to use cookies or put the variables in the URL... so that left me with hidden variables (for now). Once the dust settles, I hope to drop back in to looking at a better way of maintaining persistence with these variables I need to track.

      Believe me, I'm embarrassed by the lack of elegance of the code. I am very aware of how ugly and hard-to-maintain it is right now.

      The variables involve numerous fields (we call them attributes) that appear on each page, plus a lot of them are used to narrow down the SQL criteria for subsequent database calls. If I had more time and more knowledge, I think I'll be able to improve the code to something a little less of an embarrassing first attempt.

      The &call_vars sub was my attempt to bundle all my variables in a concatenated string to pass from page to page via a hidden field. I don't know how create a hash ref and treat the values as a bundle as you suggested.

      Lori

        The following code creates a hash and its reference. It prints from both showing that it is in fact referencing the hash. You should check perldata to get started

        #!/usr/bin/perl use strict; use warnings; my %hidden = (var_name1 => 'var_value1', var_name2 => 'var_value2'); my $hidden_ref = \%hidden; print $$hidden_ref{var_name1}; print $hidden{var_name1};


        Grygonos
      Hope you're having a better day today.      ;-)

      It turns out that the code I had posted was working correctly (at least the part that was posted). What I failed to do was put the hidden field in the form containing the buttons that download to Excel. I already had the hidden field in the form containing the cell data. Once I put the hidden field in the buttons form also, it works like a charm. I had tested my template but my assumption that the hidden field would be grabbed no matter where it was in a form was my mistake. I figured this out on my own, using my powers of alchemy.                :-D

      That's not to say there isn't vast room for improvement in my coding abilities. However, I think I should clarify something for you (and get it off my chest) since you roasted me in the Chatterbox a few days ago, suggesting I had no aptitude for programming, should know that and get out of that profession, and that I was dishonest for continuing to accept money for my work when I was so clearly over my head. I'll be honest... it hurt my feelings (yes, I need to develop a thicker skin, but it's tough when someone you respect criticizes you).

      Both you and Abigail-II are among the brightest and most skilled Perl hackers, and are very well-respected in the community. I'd like to say it doesn't matter what you think of me, but truth is, most people look up to you and when you express an opinion, they'll give it a lot more credence than the average person.

      As for what you describe as my "dishonesty" (and something along the lines of getting what you pay for when you pay a consultant $15 an hour), I believe you were assuming I was a consultant who bid on a job for which I was unqualified. I think you later realized I wasn't, so enough said about that. (By the way, I make more than twice that... is that the average beginning consultant's pay?).

      I was assigned this project by my manager; I did not ask for it. He was and is very well aware that I have absolutely no experience in this area, but as leira commented, "sometimes someone has to do it because there's no one else." Since the reports I'm currently re-writing in Perl are mine using another software package and VisualBasic, the task fell to me.

      There are also some political and economic reasons for some of the constraints I'm under. So far, that is the only drawback I have found working for a public university. I have an amazing job and an amazing chain of command; I can't imagine working anywhere else, even with the added stress over the last few months.

      I have discussed on several occasions my discomfort (and plain old inability) to meet the deadlines imposed. However, we are in the middle of a software upgrade and just because one person struggles doesn't mean the whole project gets delayed. I will bust my ass to get it done the best way I know how. That might mean crappy code right now but at least the customers will have something that works accurately. I can (and will) clean up the code later as I become more knowledgeable. It also means that I'll sometimes get roasted for asking stupid questions, but that isn't going to stop me from asking them if that's what it takes to get my job done.

      I tend to be scientific in my approach, testing out different things to see if something will work as expected. Abigail-II refers to that alchemy. However, I continually strive to do my homework, research, and testing up front before posting anything here, lest I get roasted for not doing that. I was merely trying to be thorough even though I didn't expect different results by moving stuff around.

      I am proud of the strides I've made under very difficult, demanding circumstances. Even you wrote that Perl is not an easy language to learn (or something along those lines)... yes, I have your book and I refer to it. As I have mentioned to Abigail-II in a previous post of mine, I learn by doing, not by reading. That may be a serious flaw in a programmer, but by no means a deal-breaker.

      Again, I thank you for the time you took to respond to my post. You didn't have to, and I realize that. I also realize I would be completely lost if folks like you and others hadn't helped me over the past several months, and I am grateful for their continuing support and encouragement.

      Lori

Re: Sub call isn't returning values
by Abigail-II (Bishop) on Mar 02, 2004 at 18:05 UTC
    Among other things tried:
    --I've tried removing the $|=1;.
    --I tried changing the order of &call_vars and print $CGI->header; (or Excel's mime type), but no luck.
    --I've also tried rearranging where &call_vars appears (in the loop, outside the loop).
    What do you think programming is? Alchemy? You just take some fragments of code, and shake them until it produces the right results?

    Anyway, you seemed to have tried a lot, but did you print out the value of $spec_vars? Are you sure it contains what you think it contains?

    Abigail

      As a beginner, I probably do treat programming as alchemy... especially when something isn't working, I try everything I can think of. I certainly want to make sure I do all I can before posting here (and I've learned to wear my asbestos suit!). ;-)

      Yes, I forgot to mention... I tried to print out spec_vars and it was empty after the second call to the page (which, of course, explains why variables later on in that second call are empty). However, when viewing the source at the end of the first call, the specs vars on the page have the appropriate data in them. I seem to be losing my data between the first call and the second call.

      Lori

        Lori713,
        Have you considered using the following code behind the button push:
        print $CGI->redirect( $CGI->self_url );
        I am not saying this is the most elegant solution, but it should keep the state of things between invocations.

        Cheers - L~R

        As a beginner, I probably do treat programming as alchemy... especially when something isn't working, I try everything I can think of.
        IMO, that's a very wrong thing to do. It won't teach you *anything*. If code works, or if you think it works just because it happens to produce the right output on a few test cases, it's just luck. It won't give you much insight.

        Yes, I forgot to mention... I tried to print out spec_vars and it was empty after the second call to the page (which, of course, explains why variables later on in that second call are empty).
        Well, that's a clear indication that your program isn't getting the data it's expecting. Not setting $|, calling the sub at a different time or cleaning the litter box aren't going to fix that.

        Abigail

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://333316]
Approved by kvale
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (2)
As of 2024-04-25 20:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found