The code will work with just a few additions. Maintain the data source
structure as in my article, but within each timeEntry node, add startTime2,
startTime3, startTime4 etc. nodes. Do the same for the endTime and totalTime.
Then in code, do the same for the variables at the beginning of the code. So
below
var startTimeNodeName = "my:startTime";
var endTimeNodeName = "my:endTime";
var totalHoursNodeName = "my:totalHours";
you add
var startTimeNodeName2 = "my:startTime2";
var endTimeNodeName2 = "my:endTime2";
var totalHoursNodeName2 = "my:totalHours2";
etc.
And in the function retrieveNodesAndUpdate() add additional code for the
fields you added. So below
calcAndUpdateTotalHoursNode(startTimeNode, endTimeNode, totalHoursNode);
you add
startTimeNode2 = timeEntryNode.selectSingleNode(startTimeNodeName2);
endTimeNode2 = timeEntryNode.selectSingleNode(endTimeNodeName2);
totalHoursNode2 = timeEntryNode.selectSingleNode(totalHoursNodeName2);
calcAndUpdateTotalHoursNode(startTimeNode2, endTimeNode2, totalHoursNode2);
for your second set of startTime, endTime, and totalTime fields. Do the same
for all other fields you added within the timeEntry node. Remember to declare
the variables at the beginning of the function retrieveNodesAndUpdate(). So
below
var startTimeNode = null;
var endTimeNode = null;
var totalHoursNode = null;
var timeEntryNode = null;
you add
var startTimeNode2 = null;
var endTimeNode2 = null;
var totalHoursNode2 = null;
That should do it.
---
S.Y.M. Wong-A-Ton
hello!
after changing the code i get two errors:
'totalTimeNodeName' is not defined
object expected
do i have to change something on 'update the grand total node'?
please have a look on the code!
thanks
//<namespacesDefinition>
XDocument.DOM.setProperty("SelectionNamespaces",
'xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2006-11-19T09:19:25"');
//</namespacesDefinition>
//=======
// Die folgende Handlerfunktion wurde von Microsoft Office InfoPath
erstellt.
// Der Funktionsname und die Anzahl und Namen der Argumente d?rfen
nicht ge?ndert werden.
// Diese Funktion ist dem folgenden Feld bzw. der folgenden Gruppe
zugeordnet (XPath): /my:meineFelder/my:gruppe1/my:gruppe2/my:startTime1
// Achtung: Die Informationen in diesem Kommentar werden nach dem
Erstellen des Funktionshandlers nicht aktualisiert.
//=======
function msoxd_my_startTime1::OnAfterChange(eventObj)
{
// F?gen Sie hier den Code zum Wiederherstellen des globalen Zustandes
ein.
if (eventObj.IsUndoRedo)
{
// Ein R?ckg?ngig- oder Wiederholen-Vorgang wurde durchgef?hrt
und das DOM ist schreibgesch?tzt.
return;
}
// Eine ?nderung am Feld wurde vorgenommen und das DOM ist
beschreibbar. F?gen Sie hier den Code f?r die Reaktion auf die
?nderung ein.
updateFields(eventObj.Source);
}
function msoxd_my_endTime1::OnAfterChange(eventObj)
{
// F?gen Sie hier den Code zum Wiederherstellen des globalen Zustandes
ein.
if (eventObj.IsUndoRedo)
{
// Ein R?ckg?ngig- oder Wiederholen-Vorgang wurde durchgef?hrt
und das DOM ist schreibgesch?tzt.
return;
}
// Eine ?nderung am Feld wurde vorgenommen und das DOM ist
beschreibbar. F?gen Sie hier den Code f?r die Reaktion auf die
?nderung ein.
updateFields(eventObj.Source);
}
function msoxd_my_startTime2::OnAfterChange(eventObj)
{
// F?gen Sie hier den Code zum Wiederherstellen des globalen Zustandes
ein.
if (eventObj.IsUndoRedo)
{
// Ein R?ckg?ngig- oder Wiederholen-Vorgang wurde durchgef?hrt
und das DOM ist schreibgesch?tzt.
return;
}
// Eine ?nderung am Feld wurde vorgenommen und das DOM ist
beschreibbar. F?gen Sie hier den Code f?r die Reaktion auf die
?nderung ein.
updateFields(eventObj.Source);
}
function msoxd_my_endTime2::OnAfterChange(eventObj)
{
// F?gen Sie hier den Code zum Wiederherstellen des globalen Zustandes
ein.
if (eventObj.IsUndoRedo)
{
// Ein R?ckg?ngig- oder Wiederholen-Vorgang wurde durchgef?hrt
und das DOM ist schreibgesch?tzt.
return;
}
// Eine ?nderung am Feld wurde vorgenommen und das DOM ist
beschreibbar. F?gen Sie hier den Code f?r die Reaktion auf die
?nderung ein.
updateFields(eventObj.Source);
}
/***************************************************************************
http://enterprise-solutions.swits.net/infopath/
Copyright ? 2006 S.Y.M. Wong-A-Ton, All rights reserved.
This code sample is provided "AS IS" without warranty or support of
any kind.
***************************************************************************/
/*------------------------------------------------------------------------------
This code assumes the following DOM structure:
/my:myFields/my:timeEntries/my:timeEntry/my:startTime
/my:myFields/my:timeEntries/my:timeEntry/my:endTime
/my:myFields/my:timeEntries/my:timeEntry/my:totalHours
/my:myFields/my:timeEntries/my:grandTotal
where my:timeEntry is a repeating group.
Declare the names of the nodes used in time calculations.
The names of the nodes MUST concord with the names of the
corresponding nodes in the DOM.
If a grand total field is not present, set enableGrandTotal to
false (var enableGrandTotal = false).
------------------------------------------------------------------------------*/
var startTimeNodeName1 = "my:startTime1";
var endTimeNodeName1 = "my:endTime1";
var totalTimeNodeName1 = "my:totalTime1";
var startTimeNodeName2 = "my:startTime2";
var endTimeNodeName2 = "my:endTime2";
var totalTimeNodeName2 = "my:totalTime2";
var grandTotalNodeName = "my:grandTotal";
var enableGrandTotal = true;
/*------------------------------------------------------------------------------
Calls all functions to do the time calculations and
update the total hours and grand total fields.
------------------------------------------------------------------------------*/
function updateFields(xmlNode)
{
try {
if (!isNull(xmlNode))
{
if (xmlNode.nodeType == 3)
{
if (!isNull(xmlNode.parentNode))
{
retrieveNodesAndUpdate(xmlNode.parentNode);
}
}
}
// Update the grand total
if (enableGrandTotal)
{
updateGrandTotalNode();
}
}
catch (e)
{
XDocument.UI.Alert("The following error occurred: " + e.message);
}
}
/*------------------------------------------------------------------------------
Retrieves the start time, end time, and total hours nodes
given the current context node.
------------------------------------------------------------------------------*/
function retrieveNodesAndUpdate(contextNode)
{
var startTimeNode1 = null;
var endTimeNode1 = null;
var totalTimeNode1 = null;
var startTimeNode2 = null;
var endTimeNode2 = null;
var totalTimeNode2= null;
var timeEntryNode = null;
// Retrieve parent node of context node (= time entry node)
if (!isNull(contextNode.parentNode))
{
timeEntryNode = contextNode.parentNode;
// Retrieve start time node, end time node and total hours node
startTimeNode1 = timeEntryNode.selectSingleNode(startTimeNodeName1);
endTimeNode1 = timeEntryNode.selectSingleNode(endTimeNodeName1);
totalTimeNode1 = timeEntryNode.selectSingleNode(totalTimeNodeName1);
startTimeNode2 = timeEntryNode.selectSingleNode(startTimeNodeName2);
endTimeNode2 = timeEntryNode.selectSingleNode(endTimeNodeName2);
totalTimeNode2 = timeEntryNode.selectSingleNode(totalTimeNodeName2);
// Calculate the time difference and update the total hours node
calcAndUpdateTotalTimeNode1(startTimeNode1, endTimeNode1,
totalTimeNode1);
calcAndUpdateTotalTimeNode2(startTimeNode2, endTimeNode2,
totalTimeNode2);
}
}
/*------------------------------------------------------------------------------
Calculates the elapsed time given a start time node and end time node
and writes the results to the total hours node.
------------------------------------------------------------------------------*/
function calcAndUpdateTotalTimeNode(xmlStartTimeNode, xmlEndTimeNode,
xmlTotalTimeNode)
{
if (!isNull(xmlStartTimeNode) && !isNull(xmlEndTimeNode) &&
!isNull(xmlTotalTimeNode))
{
var startTimeValue = xmlStartTimeNode.text;
var endTimeValue = xmlEndTimeNode.text;
var calcTime = "";
// Try emptying the node; if error occurs, continue
try {setNil(xmlTotalTimeNode);}
catch (e) {}
if (startTimeValue != "" && endTimeValue != "")
{
calcTime = calcTimeInMinutes(startTimeValue, endTimeValue);
}
if (calcTime != "" && xmlTotalTimeNode.getAttribute("xsi:nil"))
{
xmlTotalTimeNode.removeAttribute("xsi:nil");
}
setNodeTypedValue(xmlTotalTimeNode, calcTime / 3600);
}
}
/*------------------------------------------------------------------------------
Calculates the elapsed time given a start time and end time
in the "hh:mm" time format. Since date calculations are not
being done, the date has been set to January 1, 1970.
------------------------------------------------------------------------------*/
function calcTimeInMinutes(startTimeValue, endTimeValue)
{
var elapsed = 0;
if (startTimeValue != "" && endTimeValue != "")
{
var arrStart = startTimeValue.split(":");
var arrEnd = endTimeValue.split(":");
if (arrStart.length >= 2 && arrEnd.length >= 2)
{
var dtStart = new Date(1970, 1, 1, parseFloat(arrStart[0]),
parseFloat(arrStart[1]), 0);
var dtEnd = new Date(1970, 1, 1, parseFloat(arrEnd[0]),
parseFloat(arrEnd[1]), 0);
elapsed = (dtEnd.getTime() - dtStart.getTime()) / 1000;
}
}
return elapsed;
}
/*------------------------------------------------------------------------------
Updates the grand total node.
------------------------------------------------------------------------------*/
function updateGrandTotalNode()
{
var xmlTotalTimeNodes = XDocument.DOM.selectNodes("//" +
totalTimeNodeName);
var grandTotal = 0;
for (var i = 0; i < xmlTotalTimeNodes.length; i++)
{
if (xmlTotalTimeNodes[i].text != "")
{
grandTotal += parseFloat(xmlTotalTimeNodes[i].text);
}
}
var xmlGrandTotalNode = XDocument.DOM.selectSingleNode("//" +
grandTotalNodeName);
// Try emptying the node; if error occurs, continue
try {setNil(xmlGrandTotalNode);}
catch (e) {}
if (grandTotal != 0 && xmlGrandTotalNode.getAttribute("xsi:nil"))
{
xmlGrandTotalNode.removeAttribute("xsi:nil");
}
setNodeTypedValue(xmlGrandTotalNode, grandTotal);
}
/*------------------------------------------------------------------------------
Checks whether the value of a given node is equal to null.
Returns true if the value of a node is null, otherwise false.
------------------------------------------------------------------------------*/
function isNull(xmlNode)
{
if (xmlNode == null)
{
return true;
}
else
{
return false;
}
}
/***************************************************************************
Copyright Microsoft Corporation, All rights reserved.
This code sample is provided "AS IS" without warranty of any kind.
***************************************************************************/
/*------------------------------------------------------------------------------
Common form template functions
------------------------------------------------------------------------------*/
/*
=============================================================================
Language conversion operations
=============================================================================
*/
/*------------------------------------------------------------------------------
convertJScriptNumberToXML()
------------------------------------------------------------------------------*/
function convertJScriptNumberToXML(value)
{
var retVal;
switch (value)
{
case Number.NEGATIVE_INFINITY:
retVal = "-INF";
break;
case Number.POSITIVE_INFINITY:
retVal = "INF";
break;
//NaN == NaN returns false. Any other value is equal to itself,
//which is why the case below differentiates between NaN and
//any other valid value
case value:
retVal = value;
break;
default:
retVal = "NaN";
}
return retVal;
}
/*------------------------------------------------------------------------------
setNil() - Empty a nillable element.
S.Y.M. Wong-A-Ton: Replaced xpath parameter by xmlNode parameter.
------------------------------------------------------------------------------*/
function setNil(xmlNode)
{
if (!xmlNode || xmlNode.text == "")
return;
// Create xsi:nil attribute with the proper namespace.
var xmlNil = xmlNode.ownerDocument.createNode(2, "xsi:nil",
"http://www.w3.org/2001/XMLSchema-instance");
xmlNil.text = "true";
// The order is important.
xmlNode.text = "";
xmlNode.setAttributeNode(xmlNil);
}
/*------------------------------------------------------------------------------
setNodeTypedValue() - Use instead of setNodeValue() if you want
to format the value by MSXML according to data type (from schema).
Use this when setting floating point and decimal values. These
values are formatted differently in some locales and will cause
schema
validation errors when set using setNodeValue or a node's text
property.
NOTE: this is not really useful for dates in Jscript.
S.Y.M. Wong-A-Ton: Replaced xpath parameter by xmlNode parameter.
------------------------------------------------------------------------------*/
function setNodeTypedValue(xmlNode, value)
{
if (!xmlNode)
return;
// The xsi:nil needs to be removed before we set the value.
if (value != "" && xmlNode.getAttribute("xsi:nil"))
xmlNode.removeAttribute("xsi:nil");
var convertedValue = convertJScriptNumberToXML(value);
// Setting the value would mark the document as dirty.
// Let's do that if the value has really changed.
if (xmlNode.nodeTypedValue != convertedValue)
xmlNode.nodeTypedValue = convertedValue;
}
S.Y.M. Wong-A-Ton - 19 Nov 2006 19:10 GMT
No. Change
var enableGrandTotal = true;
to
var enableGrandTotal = false;
at the very top of the code and you should be fine.
---
S.Y.M. Wong-A-Ton
> hello!
>
[quoted text clipped - 292 lines]
>
> /*------------------------------------------------------------------------------
sproecky - 24 Nov 2006 21:22 GMT
hello!
the code is working perfect!
thank you very much!!
sproecky
sproecky - 24 Nov 2006 21:52 GMT
hello!
i have one more question:
i tried the code with 3 start and end times and it woks well.
now i tried to put some more start and end times into the section
but only the thirst 3 lines are able to calculate the totalTime!?
what do i have to do? because everytime to write the code completely
new takes a long time!?
best regards
sproecky
sproecky - 24 Nov 2006 21:57 GMT
i found the problem..... thanks