Books
in black and white
Main menu
Share a book About us Home
Books
Biology Business Chemistry Computers Culture Economics Fiction Games Guide History Management Mathematical Medicine Mental Fitnes Physics Psychology Scince Sport Technics
Ads

Excel add in development in C++ Aplications in finance - Dalton S.

Dalton S. Excel add in development in C++ Aplications in finance - Wiley publishing , 2005. - 425 p.
ISBN 0-470-02469-0
Download (direct link): exceladdindevelopmentincand2005.pdf
Previous << 1 .. 130 131 132 133 134 135 < 136 > 137 138 139 140 141 142 .. 168 >> Next

9.10.8 The task interface and main functions
In this example, the only constraint on the interface function is that it is registered as volatile. It is also helpful to register it as a macro-sheet equivalent function which only takes oper arguments. Its responsibilities are:
1. To validate arguments and place them into an array of xlopers.
2. To call TaskList::UpdateTask().
3. To interpret the returned value of UpdateTask() and pass something appropriate back to the calling cell.
The associated function that does the work is constrained, in this case, by the implementation of the TaskList class and the task structure, to be a function that takes a pointer to a task and returns a bool. The following code shows an example interface and main function pair. The long task in this case counts from one to the value of its one argument. (This is a useful test function, given its predictable execution time.) Note that long_task_example_main () regularly checks the state of the break_task flag. It also regularly calls Sleep(0), a very small overhead, in order to make thread management easier for the operating system.
// LongTaskExampleMain() executes the task and does the work.
// It is only ever called from the background thread. It is // required to check the break_task flag regularly to see if the // foreground thread needs execution to stop. It is not required // that the task populates the return value, fn_ret_val, as it does // in this case. It could just wait till the final result is known. bool long_task_example_main(tag_task *pTask)
{
long limit;
if(pTask->arg_array[0].xltype != xltypeNum || (limit = (long)pTask->arg_array[0].val.num) < 1) return false;
pTask->fn_ret_val.xltype = xltypeNum; pTask->fn_ret_val.val.num = 0;
for(long i = 1; i <= limit; i++)
{
if(i % 1000)
{
if(pTask->break_task) return false;
Miscellaneous Topics 329
Sleep(0);
}
pTask->fn_ret_val.val.num = (double)i;
}
return true;
}
The interface function example below shows how the TaskList class uses Excel error values to communicate back to the interface function some of the possible states of the task. It is straightforward to make this much richer if required.
// LongTaskExampleInterface() is a worksheet function called // directly by Excel from the foreground thread. It is only // required to check arguments and call ExampleTaskList.UpdateTask() // which returns either an error, or the intermediate or final value // of the calculation. UpdateTask() errors can be returned directly // or, as in this case, the function can return the current // (previous) value of the calling cell. This function is registered
// with Excel as a volatile macro sheet function.
xloper * stdcall LongTaskExampleInterface(xloper *arg)
{
if(called_from_paste_fn_dlg()) return p_xlErrNa;
if(arg->xltype != xltypeNum || arg->val.num < 1) return p_xlErrValue;
xloper arg_array[1]; // only 1 argument in this case static xloper ret_val;
// UpdateTask makes deep copies of all the supplied arguments
// so passing in an array of shallow copies is safe.
arg_array[0] = *arg;
//As there is only one argument in this case, we could instead // simply pass a pointer to this instead of creating the array ret_val = ExampleTaskList.UpdateTask(long_task_example_main, arg_array, 1);
if(ret_val.xltype == xltypeErr)
{
switch(ret_val.val.err)
{
// the arguments were not valid case xlerrValue: break;
// task has never been completed and is now pending or current case xlerrNum: break;
// the thread is inactive case xlerrNA: break;
}
// Return the existing cell value.
get_calling_cell_value(ret_val);
330
Excel Add-in Development in C/C++
}
ret_val.xltype |= xlbitDLLFree; // memory to be freed by the DLL return &ret_val;
}
9.10.9 The polling command
The polling command only has the following two responsibilities:
• Detect when a recalculation is necessary in order to update the values of volatile long task functions. (In the example code below the recalculation is done on every call into the polling function.)
• Reschedule itself to be called again in a number of seconds determined by a configurable TaskList class data member.
int stdcall long_task_polling_cmd(void)
{
if(ExampleTaskList.m_BreakPollingCmdFlag)
return 0; // return without rescheduling next call
// Run through the list of tasks setting TASK_READY tasks to // TASK_UNCLAIMED. Tasks still unclaimed after recalculation are // assumed to be orphaned and deleted by DeleteUnclaimedTasks(). bool need_racalc = ExampleTaskList.SetDoneTasks();
// if(need_racalc) // Commented out in this example {
// Cause Excel to recalculate. This forces all volatile fns to be // re-evaluated, including the long task functions, which will then // return the most up-to-date values. This also causes status of // tasks to be changed to TASK_COMPLETE from TASK_UNCLAIMED. Excel4(xlcCalculateNow, NULL, 0);
// Run through the list of tasks again to clean up unclaimed tasks ExampleTaskList.DeleteUnclaimedTasks();
Previous << 1 .. 130 131 132 133 134 135 < 136 > 137 138 139 140 141 142 .. 168 >> Next