I think there are two alternatives to your loop over all chars from the fieldvalues. One could be a RegEx approach like described here: http://www.qlikfix.com/2010/10/18/regular-expressions-in-the-load-script/ and the other to use a mapsubstring() maybe similar to this one:
load F1 & iterno() while iterno() <= 999999;
load chr(64 + recno()) as F1 autogenerate 26;
This won't be a small table but it wouldn't be too huge to be usable. Whereby I'm not sure if you really need to create this as a large generic table - your patient numbers should be already available in any fact- or dimension-table. In this case your mapping-table would be look like:
mapping load distinct [Patient Number], '<' & [Patient Number] & '>' from YourTable;
load *, textbetween(mapsubstring('Map', FreeText), '<', '>') as [Patient Number] from TableWithFreeText;
Depending on the text you might need a different delimiter for textbetween() which definitely exists within the text, for example a chr(1) should be quite unlikely.
May be something like this..
Load * Inline
IF(IsNUm(Mid(TTT,IterNo()+1,1)) AND IsNUm(Mid(TTT,IterNo()+2,1)) And IsNUm(Mid(TTT,IterNo()+3,1))And IsNUm(Mid(TTT,IterNo()+4,1)) And IsNUm(Mid(TTT,IterNo()+5,1)) and Istext(Mid(TTT,IterNo(),1)),IterNo(),0) as IndexOfPatNo
Mid(TTT,IndexOfPatNo,7) as PatientNumber,