Solved

Need an intelligent, spreadsheet style grid

Posted on 2003-12-10
16
375 Views
Last Modified: 2013-12-24

In a cfform I've got a cfgrid component that list rows of employees with columns representing hours worked for each day in a week with a Total Hours column as the last column. The user enters in hours for each day and when they press submit the action page adds them all together and populate to totals.  Works fine.

Client now wants the grid to display a running total in the Total Hours field as they enter values in each day, so that if they enter 8 for Monday, the Total Hours column for that row will show 8, then they enter 8 in Tuesday's Hours and the Total Hours increments to 16.   This needs to happen dynamically as they enter values without having to press submit.

I don't think cfgrid can do this.  Does anyone have any ideas on the best way to accomplish this?

Thanks,
Stephen
0
Comment
Question by:Waterstone
  • 6
  • 6
  • 4
16 Comments
 
LVL 12

Expert Comment

by:jyokum
ID: 9918144
<script>
var wk=new Array('sun','mon','tue','wed','thu','fri','sat');

function sumTime(row){
      var t=0;
      tot=eval('document.frmData.total'+row);
      for(i=0;i<=6;i++){
            fld=eval('document.frmData.'+wk[i]+row);
            t+=fld.value*1;
      }
      tot.value=t;
}
</script>

<form name="frmData">
<table border="1" bordercolor="#CCCCCC" cellpadding="0" cellspacing="0">
<tr>
      <td>Employee</td>
      <td>Sun</td>
      <td>Mon</td>
      <td>Tue</td>
      <td>Wed</td>
      <td>Thu</td>
      <td>Fri</td>
      <td>Sat</td>
      <td>TOTAL</td>
</tr>
<cfset row=1>
<cfoutput>
<cfloop list="bob,sally,jane,billy" index="emp">
<tr>
      <td>#emp#</td>
      <td><input type="text" name="sun#row#" onChange="sumTime(#row#);" style="width: 50px;"></td>
      <td><input type="text" name="mon#row#" onChange="sumTime(#row#);" style="width: 50px;"></td>
      <td><input type="text" name="tue#row#" onChange="sumTime(#row#);" style="width: 50px;"></td>
      <td><input type="text" name="wed#row#" onChange="sumTime(#row#);" style="width: 50px;"></td>
      <td><input type="text" name="thu#row#" onChange="sumTime(#row#);" style="width: 50px;"></td>
      <td><input type="text" name="fri#row#" onChange="sumTime(#row#);" style="width: 50px;"></td>
      <td><input type="text" name="sat#row#" onChange="sumTime(#row#);" style="width: 50px;"></td>
      <td><input type="text" name="total#row#"></td>
</tr>
<cfset row=row+1>
</cfloop>
</cfoutput>
</table>
</form>

you would probably be changing this to loop over a recordset instead of a list
0
 

Author Comment

by:Waterstone
ID: 9918237
jyokum,

Thank you for such a swift reply.  You are right, I'd need to create a table based on the recordset returned by a cfquery.  The recordset has an entry for each employee with a field for each day and some total field.  I would need to populate the table grid with the existing records, then update the records with the new values.  I do this with CFgrid now.  How difficult is it to replace the list with a cfquery record set?

I can send along the cfquery code if it would help.

Thanks again for sharing your expertise.

Stephen
0
 
LVL 11

Expert Comment

by:hart
ID: 9918252
<CFQUERY NAME="Qry_GetEmployees" DATASOURCE="DsnName">
      Your query which gets the employee names and their daily work hours...
</CFQUERY>

<HTML>
<HEAD>
<TITLE>Report</TITLE>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript">
<!--
function CalTotal(sfield,eid)
{
      if(!isNaN(eval("document.frm." + sfield + ".value")) || eval("document.frm." + sfield + ".value") > 24)
      {
            alert("Please enter work hours for the day properly")
            eval("document.frm." + sfield + "").focus();
            eval("document.frm." + sfield + "").select();
            return false;
      }
      else
      {
            eval("document.frm.tot" + eid + "").value = parseInt(eval("document.frm.mon" + eid + ".value")) + parseInt(eval("document.frm.tue" + eid + ".value")) + parseInt(eval("document.frm.wed" + eid + ".value")) + parseInt(eval("document.frm.thu" + eid + ".value")) + parseInt(eval("document.frm.fri" + eid + ".value")) + parseInt(eval("document.frm.sat" + eid + ".value"));
      }
}
//-->
</SCRIPT>
</HEAD>
<BODY>
<FORM name="frm" action="actionpage.cfm" method="post">
      <TABLE CELLSPACING="0" CELLPADDING="0" BORDER="1" WIDTH="100%">
            <TR>
                  <TD>Employee Name</TD>
                  <TD>Monday</TD>
                  <TD>Tuesday</TD>
                  <TD>Wednesday</TD>
                  <TD>Thursday</TD>
                  <TD>Friday</TD>
                  <TD>Saturday</TD>            
                  <TD>Total</TD>
            </TR>
            <CFOUTPUT QUERY="Qry_GetEmployees">
                  <TR>
                        <TD>#employeename#</TD>
                        <TD><INPUT Type="text" Name="mon#employeeid#" Value="#value from database for monday#" OnBlur="CalTotal('mon#employeeid#','#employeeid#')">&nbsp;hrs</TD>
                        <TD><INPUT Type="text" Name="tue#employeeid#" Value="#value from database for tuesday#" OnBlur="CalTotal('tue#employeeid#','#employeeid#')">&nbsp;hrs</TD>
                        <TD><INPUT Type="text" Name="wed#employeeid#" Value="#value from database for wed#" OnBlur="CalTotal('wed#employeeid#','#employeeid#')">&nbsp;hrs</TD>
                        <TD><INPUT Type="text" Name="thu#employeeid#" Value="#value from database for thur#" OnBlur="CalTotal('thu#employeeid#','#employeeid#')">&nbsp;hrs</TD>
                        <TD><INPUT Type="text" Name="fr#employeeid#" Value="#value from database for fri#" OnBlur="CalTotal('fri#employeeid#','#employeeid#')">&nbsp;hrs</TD>
                        <TD><INPUT Type="text" Name="sat#employeeid#" Value="#value from database for sat#" OnBlur="CalTotal('sat#employeeid#','#employeeid#')">&nbsp;hrs</TD>                        
                        <CFSET nTotalHrs = Add up all the values of the days like this [Evaluate(value from database for monday + value from database for tuesday).. etc]>
                        <TD><INPUT Type="text" Name="tot#employeeid#" Value="#nTotalHrs#" DISABLED>&nbsp;hrs</TD>
                  </TR>                  
            </CFOUTPUT>            
      </TABLE>
</FORM>
</BODY>
</HTML>

PS: Remeber, if there is no value in the database for mon / any other day please show 0 by default in the text boxes...

other wise u will have to check for each and every text box while calculating...


Regards
Hart
0
 
LVL 11

Expert Comment

by:hart
ID: 9918259
use parseInt while adding numerical vaues in javascript other wise it will just append it as string...

0
 
LVL 12

Expert Comment

by:jyokum
ID: 9918284
> use parseInt while adding numerical vaues
OR just multiply by 1, same effect

Waterstone,
send your current query. I could make up an example but may as well use your code if you already have something
0
 
LVL 11

Expert Comment

by:hart
ID: 9918314
oh sorry jyokum...
0
 
LVL 11

Expert Comment

by:hart
ID: 9918349
small changes in my post,

Name="fr#employeeid#" should be Name="fri#employeeid#"

and change this line
if(!isNaN(eval("document.frm." + sfield + ".value")) || eval("document.frm." + sfield + ".value") > 24)


to

if(isNaN(eval("document.frm." + sfield + ".value")) || eval("document.frm." + sfield + ".value") > 24 || eval("document.frm." + sfield + ".value")  == '')

also change onBlur() to OnChange()...


PS : Jyokum the thing was i was typing my code in the intranet and i had not refreshed the question, but then after i posted my code i saw 2 comments one from u and the one of waterstone. :-)

PS : WaterStone, plz do award the points to jyokum :-)

Regards
Hart

0
 

Author Comment

by:Waterstone
ID: 9919506

jyokum,

Good morning!  Here's the query I use to load the cfgrid.

<!---  =================================================   --->

  <cfquery name="GetRecords" datasource="mtcdata" username="username" password="password">
         select  CompanyCode,
                           DepartmentCode,
                                 WeekEndingDate,
                                 CONVERT(varchar, WeekEndingDate, 10) AS WeekEndDate ,
                           LastName,                          
                               EmployeeNumber,
                               JobRSN,
                              FirstName,                            
                      RegHours,
                                OTHours,
                                DoubleHours,
                                TotalHours,
                                SunRegHours,
                                MonRegHours,
                                TueRegHours,
                                WedRegHours,
                                ThuRegHours,
                                FriRegHours,
                                SatRegHours,
                                Approver                          
    from TimeCard  
    Where CompanyCode = '#COCODE#' AND                 
                  WeekEndingDate = '#WeekTime#'
    Order by LastName, FirstName, EmployeeNumber
  </cfquery>

and here's the cfgrid code so ou can see how the fields are presented.

<!---  =================================================   --->
<cfgrid name="time_grid"
    height=250
      width=760
    vspace=0
    selectmode="edit"
    query="GetRecords"
      rowHeaders="No"
      colHeaderTextColor="##3D8FDB"
      colHeaderBold="Yes"
      colHeaderAlign = "Center"      
      onValidate="validateHours"
      onError="HoursError">

    <cfgridcolumn name="FirstName"
        header="First  Name"
      width=125
     headeralign="center"
     headerbold="Yes"
       bgColor="##C9D9E9"
       select="No">

    <cfgridcolumn name="LastName"
        header="Last Name"
       width=125
       headeralign="center"
       headerbold="Yes"
         bgColor="##C9D9E9"
         select="No">
        
      <cfgridcolumn name="EmployeeNumber"
        header="Emp No"
      width=50
      headeralign="center"
      headerbold="Yes"
        bgColor="##C9D9E9"
      select="No">         
        
      <cfgridcolumn name="WeekEndDate"
        header="Wk End"
       width=60
       headeralign="center"
       headerbold="Yes"
         bgColor="##C9D9E9"
         select="No">
                                
        <cfgridcolumn name="SunRegHours"
         type="numeric"
         header="Sun"
       width=30
       headeralign="center"
       headerbold="Yes"
         numberFormat="___.__"
         dataAlign = "right"
         textColor = "(CX GT 24 ? red : black)"
         bgColor="##EDF5FD"
         select="Yes">
                                
        <cfgridcolumn name="MonRegHours"
         type="numeric"
         header="Mon"
       width=30
       headeralign="center"
       headerbold="Yes"
         numberFormat="___.__"
         dataAlign = "right"
         textColor = "(CX GT 24 ? red : black)"
         bgColor="##EDF5FD"         
         select="Yes">                                 
                                
        <cfgridcolumn name="TueRegHours"
         type="numeric"
         header="Tue"
       width=30
       headeralign="center"
       headerbold="Yes"
         numberFormat="___.__"
         dataAlign = "right"
         textColor = "(CX GT 24 ? red : black)"
         bgColor="##EDF5FD"
         select="Yes">                                 
                                
        <cfgridcolumn name="WedRegHours"
         type="numeric"
         header="Wed"
       width=30
       headeralign="center"
       headerbold="Yes"
         numberFormat="___.__"
         dataAlign = "right"
         textColor = "(CX GT 24 ? red : black)"
         bgColor="##EDF5FD"
         select="Yes">                                 
                                
        <cfgridcolumn name="ThuRegHours"
          type="numeric"
         header="Thu"
       width=30
       headeralign="center"
       headerbold="Yes"
         numberFormat="___.__"
         dataAlign = "right"
         bgColor="##EDF5FD"
         select="Yes">                                 
                                
        <cfgridcolumn name="FriRegHours"
          type="numeric"
         header="Fri"
       width=30
       headeralign="center"
       headerbold="Yes"
         numberFormat="___.__"
         dataAlign = "right"
         textColor = "(CX GT 24 ? red : black)"
         bgColor="##EDF5FD"
         select="Yes">
        
        <cfgridcolumn name="SatRegHours"
          type="numeric"
         header="Sat"
       width=30
       headeralign="center"
       headerbold="Yes"
         numberFormat="___.__"
         dataAlign = "right"
         textColor = "(CX GT 24 ? red : black)"
         bgColor="##EDF5FD"
         select="Yes">         
        
        <cfgridcolumn name="RegHours"
          type="numeric"
         header="Reg "
       width=40
       headeralign="center"
       headerbold="Yes"
         numberFormat="___.__"
         dataAlign = "right"
         bgColor="##C9D9E9"
         select="No">
                                
        <cfgridcolumn name="OTHours"
          type="numeric"
         header="OT"
       width=30
       headeralign="center"
       headerbold="Yes"
         numberFormat="___.__"
         dataAlign = "right"
         bgColor="##E0EEFC"
         select="Yes">                                 
                                
        <cfgridcolumn name="DoubleHours"
          type="numeric"
         header="Dbl"
       width=30
       headeralign="center"
       headerbold="Yes"
         numberFormat="___.__"
         dataAlign = "right"
         bgColor="##E0EEFC"         
         select="Yes">
                                         
        <cfgridcolumn name="TotalHours"         
         header="Tot"
       width=40
       headeralign="center"
       headerbold="Yes"
         numberFormat="___.__"
         dataAlign = "right"
         bgColor="##C9D9E9"
         type="numeric"
         select="No">         
                        
       <cfgridcolumn name="DepartmentCode"
      display="No">  
        
       <cfgridcolumn name="JobRSN"
      display="No">  
        
    <cfgridcolumn name="CompanyCode"
        display="No">  
        
      <cfgridcolumn name="WeekEndingDate"
        display="No">
        
  </cfgrid>

Best Regrads
0
Superior storage. Superior surveillance.

WD Purple drives are built for 24/7, always-on, high-definition security systems. With support for up to 8 hard drives and 32 cameras, WD Purple drives are optimized for surveillance.

 
LVL 12

Accepted Solution

by:
jyokum earned 500 total points
ID: 9926157
just for the sake of being lazy, i didn't include all your columns but this should get you going

<cfquery name="GetRecords" datasource="mtcdata" username="username" password="password">
select
      LastName,                      
      EmployeeNumber,
      SunRegHours,
      MonRegHours,
      TueRegHours,
      WedRegHours,
      ThuRegHours,
      FriRegHours,
      SatRegHours              
from TimeCard  
Order by LastName, EmployeeNumber
</cfquery>

<script>
var wk=new Array('sun','mon','tue','wed','thu','fri','sat');

function initTime(){
      var emps=new Array(<cfoutput>#ValueList(GetRecords.EmployeeNumber)#</cfoutput>);
      var i;
      for(i=0;i<emps.length;i++) sumTime(emps[i]);
}

function sumTime(row){
      var t=0;
      var i;
      tot=eval('document.frmData.total'+row);
      for(i=0;i<=6;i++){
            fld=eval('document.frmData.'+wk[i]+row);
            fld.value>24 ? fld.style.color='red' : fld.style.color='black';
            t+=fld.value*1;
      }
      tot.value=t;
}
</script>

<form name="frmData">
<table border="1" bordercolor="#CCCCCC" cellpadding="0" cellspacing="0">
<tr>
      <td>Employee</td>
      <td>Sun</td>
      <td>Mon</td>
      <td>Tue</td>
      <td>Wed</td>
      <td>Thu</td>
      <td>Fri</td>
      <td>Sat</td>
      <td>TOTAL</td>
</tr>
<cfoutput query="GetRecords">
<tr>
      <td>#GetRecords.LastName# (ID: #GetRecords.EmployeeNumber#)</td>
      <td><input type="text" name="sun#GetRecords.EmployeeNumber#" value="#Val(GetRecords.SunRegHours)#" onChange="sumTime(#GetRecords.EmployeeNumber#);" style="width: 50px;"></td>
      <td><input type="text" name="mon#GetRecords.EmployeeNumber#" value="#Val(GetRecords.MonRegHours)#" onChange="sumTime(#GetRecords.EmployeeNumber#);" style="width: 50px;"></td>
      <td><input type="text" name="tue#GetRecords.EmployeeNumber#" value="#Val(GetRecords.TueRegHours)#" onChange="sumTime(#GetRecords.EmployeeNumber#);" style="width: 50px;"></td>
      <td><input type="text" name="wed#GetRecords.EmployeeNumber#" value="#Val(GetRecords.WedRegHours)#" onChange="sumTime(#GetRecords.EmployeeNumber#);" style="width: 50px;"></td>
      <td><input type="text" name="thu#GetRecords.EmployeeNumber#" value="#Val(GetRecords.ThuRegHours)#" onChange="sumTime(#GetRecords.EmployeeNumber#);" style="width: 50px;"></td>
      <td><input type="text" name="fri#GetRecords.EmployeeNumber#" value="#Val(GetRecords.FriRegHours)#" onChange="sumTime(#GetRecords.EmployeeNumber#);" style="width: 50px;"></td>
      <td><input type="text" name="sat#GetRecords.EmployeeNumber#" value="#Val(GetRecords.SatRegHours)#" onChange="sumTime(#GetRecords.EmployeeNumber#);" style="width: 50px;"></td>
      <td><input type="text" name="total#GetRecords.EmployeeNumber#"></td>
</tr>
</cfoutput>
</table>
</form>

<script>initTime();</script>
0
 

Author Comment

by:Waterstone
ID: 9950189
Thanks for all the help, jyokum.

I'll post another question as a follow up.

What is the best way to use the table to update the database when I add the submit button?
How do I loop through the rows of the table to update the datase using a cfquery?

Thanks for any info you can pas along.
0
 

Author Comment

by:Waterstone
ID: 9952219
Hello jyokum,

Could you clarify one point for me?  Which javascript statement assigns the value of tot to the input field <td><input type="text" name="total#GetRecords.EmployeeNumber#"></td>?

Does tot=eval('document.frmData.total'+row);
connect the variable tot to the field referenced by the eval statement, so that whenever the vsriable tot changes the value is reflected in 'document.frmData.total'+row ?

Thanks,
Waterstone
0
 
LVL 12

Expert Comment

by:jyokum
ID: 9952389
tot.value=t;         << this is the statement that actually assigns is.

the eval statement sets up the reference to the field
0
 

Author Comment

by:Waterstone
ID: 9952434


So as tot changes the value of ="total#GetRecords.EmployeeNumber#" reflects the change?
0
 
LVL 12

Expert Comment

by:jyokum
ID: 9952452
yes

assuming GetRecords.EmployeeNumber = 100...
tot is really just a pointer to document.frmData.total100

if GetRecords.EmployeeNumber = 101

tot = document.frmData.total101
0
 

Author Comment

by:Waterstone
ID: 9952507


So the eval statement is a two-way poniter to the field it references?
Once tot is set up to reference the field, any changes to tot are automatically reflected in the field referenced by the eval statement?

Sorry to be so dense here, just want to be sure I underastand it completely.
0
 
LVL 12

Expert Comment

by:jyokum
ID: 9952521
the javascript eva() function is similar to the coldfusion evaluate() function

http://www.devguru.com/Technologies/ecmascript/quickref/eval.html
0

Featured Post

Get up to 2TB FREE CLOUD per backup license!

An exclusive Black Friday offer just for Expert Exchange audience! Buy any of our top-rated backup solutions & get up to 2TB free cloud per system! Perform local & cloud backup in the same step, and restore instantly—anytime, anywhere. Grab this deal now before it disappears!

Join & Write a Comment

Most ColdFusion developers get confused between the CFSet, Duplicate, and Structcopy methods of copying a Structure, especially which one to use when. This Article will explain the differences in the approaches with examples; therefore, after readin…
One of the typical problems I have experienced is when you have to move a web server from one hosting site to another. You normally prepare all on the new host, transfer the site, change DNS and cross your fingers hoping all will be ok on new server…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now