Your code is processing the first folder, and for each subfolder it finds, it adds it to the array of folders to be processed, then processes each of those in turn etc. etc. Seems like one approach would be to prepend the current folder name to any new folders added to the array, as a way to get hold of the current path, then use that path to check/create folders as necessary before moving files to the archive folder.
So here:
If StringInstr(FileGetAttrib ( $n_tFile ),"D") > 0 then
If $T_Incl_SubDir = 1 then
$T_DirCount = $T_DirCount + 1
$n_Dirnames[$T_DirCount][0] = $n_tFile
$n_Dirnames[$T_DirCount][1] = 0
EndIf
Else
change $n_Dirnames[$T_DirCount][0] = $n_tFile to be $n_Dirnames[$T_DirCount][0] = $n_Dirnames[$n_DirCount][0] & "\" & $n_tFile.
And here:
$rc = FileMove ($n_tFile, "c:\archive\salesreports")
put code before this that tests to see if StringReplace($n_Dirnames[$n_DirCount][0], "C:\salesreports", "c:\archive\salesreports") exists, and if not creates the appropriate subfolders - maybe in a Func that StringSplits the current folder, tests each level in turn, and when it gets to the subfolder(s) that don't exist, creates them.