I think for a start u might have missed a point about dynamicly named vars (then again my head started to hurt trying to read this thread)

//set % $+ $2 $+ .name -
//echo $(% $+ $2 $+ .name -,2)

more preferably
//set $+(%,$2,.name) -
//echo $($+(%,$2,.name),2)

The reason for this is, in the SET your not evaluating the var name at all the word SET well cause mirc to go "oh wow i better not get the contents of this since im setting something into it.
aka
//SET %blah frog
//SET %blah dog
it would be no good if in the second line mirc went "well %Blah is frog, so we have //SET frog dog"

And in any access of the var, mirc needs to be told, it needs to evaluate this twice instead of once, becuase the first evaluation puts the var name together, the second then evalautes it for its contents.
//echo $+(%,bl,ah)
%blah
//echo $($+(%,bl,ah),2)
dog

Try this ** Im assuming this is example code, as you might as well just /write template.txt -_-_-_-_-_-_-_- **
Code:
on 1:TEXT:!add*:#: {
  if (($chan == %chan) && ($0 >= 2)) {
    set $+(%,$2,.name) - 
    set $+(%,$2,.surname) -
    set $+(%,$2,.address) -
    set $+(%,$2,.phone) -
    set $+(%,$2,.spend) -
    set $+(%,$2,.advance) -
    set $+(%,$2,.coffee) -
    set $+(%,$2,.final) -
    write template.txt $+( $($+(%,$2,.name),2) , _ , $($+(%,$2,.surname),2) , _ , $($+(%,$2,.address),2) , _ , $($+(%,$2,.phone),2) , _ , $($+(%,$2,.spend),2) , _ , $($+(%,$2,.advance),2) , _ , $($+(%,$2,.coffee),2) , _ , $($+(%,$2,.final),2) )
  }
}


just to be clear $($+(%,$2,.name),2) is accessing the dynamic var, around that is $+( var , _ , var , _ , etc etc )