у многих ответов были полезные идеи, но ни один из них не соответствовал моим потребностям. Поэтому я использовал все идеи и создал этот пример:
function Format_Numb( fmt){
var decimals = isNaN(decimals) ? 2 : Math.abs(decimals);
if(typeof decSgn==="undefined") decSgn = ".";
if(typeof kommaSgn==="undefined") kommaSgn= ",";
var s3digits=/(\d{1,3}(?=(\d{3})+(?=[.]|$))|(?:[.]\d*))/g;
var dflt_nk="00000000".substring(0,decimals);
//--------------------------------
// handler for pattern: "%m"
var _f_money= function( v_in){
var v=v_in.toFixed(decimals);
var add_nk=",00";
var arr= v.split(".");
return arr[0].toString().replace(s3digits, function ([110]) {
return ([110].charAt(0)==".")
? ((add_nk=""),(kommaSgn + [110].substring(1)))
: ([110] + decSgn);
})
+ ( (decimals > 0)
? ( kommaSgn
+ (
(arr.length > 1)
? arr[1]
: dflt_nk
)
)
: ""
);
}
// handler for pattern: "%<len>[.<prec>]f"
var _f_flt= function( v_in,l,prec){
var v=(typeof prec !== "undefined") ? v_in.toFixed(prec):v_in;
return ((typeof l !== "undefined")&&( (l=l-v.length) > 0))
?(Array(l+1).join(" ") + v)
:v;
}
// handler for pattern: "%<len>x"
var _f_hex= function( v_in,l,flUpper){
var v= Math.round(v_in).toString(16);
if(flUpper) v=v.toUpperCase();
return ((typeof l !== "undefined")&&( (l=l-v.length) > 0))
?(Array(l+1).join("0") + v)
:v;
}
//...can be extended..., just add the function, f.e.: var _f_octal= function( v_in,...){
//--------------------------------
if( typeof(fmt)!=="undefined"){
//...can be extended..., just add the char,f.e."O": MFX -> MFXO
var rpatt=/(?:%([^%"MFX]*)([MFX]))|(?:"([^"]*)")|("|%%)/gi;
var _qu= "\"";
var _mask_qu= "\\\"";
var str= fmt.toString().replace( rpatt,function([110],$1,$2,$3,$4){
var f;
if(typeof $1 !== "undefined"){
switch($2.toUpperCase()){
case "M": f= "_f_money(v)"; break;
case "F": var n_dig0,n_dig1;
var re_flt=/^(?:(\d))*(?:[.](\d))*$/;
$1.replace(re_flt,function([110],$1,$2){
n_dig0=$1;
n_dig1=$2;
});
f= "_f_flt(v," + n_dig0 + "," + n_dig1 + ")"; break;
case "X": var n_dig="undefined";
var re_flt=/^(\d*)$/;
$1.replace(re_flt,function([110]){
if([110]!="")n_dig=[110];
});
f= "_f_hex(v," + n_dig + "," + ($2=="X") + ")"; break;
//...can be extended..., f.e.: case "O":
}
return "\"+"+f+"+\"";
} else if(typeof $3 !== "undefined"){
return _mask_qu + $3 + _mask_qu;
} else {
return ($4==_qu)?_mask_qu:$4.charAt(0);
}
});
var cmd= "return function(v){"
+ "if(typeof v === \"undefined\")return \"\";" //null returned as empty string
+ "if(!v.toFixed)return v.toString();" //not numb returned as string
+ "return \"" + str + "\";"
+ "}";
//...can be extended..., just add the function name in the 2 places:
return new Function( "_f_money,_f_flt,_f_hex", cmd)(_f_money,_f_flt,_f_hex);
}
}
Во-первых, мне нужно было определение формата строки в стиле C , которое должно быть гибким, но очень простым использовать , и я определил его следующим образом; паттерны:
%[<len>][.<prec>]f float, example "%f", "%8.2d", "%.3f"
%m money
%[<len>]x hexadecimal lower case, example "%x", "%8x"
%[<len>]X hexadecimal upper case, example "%X", "%8X"
, поскольку нет необходимости форматировать другие, тогда как для меня Евро, я реализовал только "% m". Но это легко расширить ... Как и в C, строка формата - это строка, содержащая шаблоны, например. для евро : «% m €» (возвращает строки типа «8.129,33 €»)
Помимо гибкости, мне нужно было очень быстрое решение для таблицы обработки . Это означает, что при обработке тысяч ячеек обработку строки формата нельзя выполнять более одного раза . Вызов типа "format (value, fmt)" для меня неприемлем, но его нужно разделить на два этапа:
// var formatter = Format_Numb( "%m €");
//simple example for Euro...
// but we use a complex example:
var formatter = Format_Numb("a%%%3mxx \"zz\"%8.2f°\" >0x%8X<");
// formatter is now a function, which can be used more than once (this is an example, that can be tested:)
var v1= formatter( 1897654.8198344);
var v2= formatter( 4.2);
... (and thousands of rows)
Также для производительности _f_money заключает в себе регулярное выражение;
В-третьих, вызов типа «format (value, fmt)» неприемлем, потому что: хотя должна быть возможность форматировать разные коллекции объектов (например, ячеек столбца) с разными масками, я не хочу, чтобы что-то обрабатывалось форматирование строк в точке обработки. На данный момент я хочу только использовать форматирование, как в
для (var cell in cell) {do_something (cell.col.formatter (cell.value)); }
Какой формат - может быть, он определен в ini, в xml для каждого столбца или где-то еще ..., но анализирует и устанавливает форматы или имеет дело с интернационализацией ] обрабатывается в совершенно другом месте , и там я хочу назначить средство форматирования для коллекции, не думая о проблемах производительности:
col.formatter = Format_Numb (_getFormatForColumn (...)) ;
В-четвертых, я хотел «толерантное» решение , поэтому прохождение fe строка вместо числа должна возвращать просто строку, но «null» должна возвращать пустую строку.
(Также форматирование «% 4.2f» не должно обрезать что-либо, если значение слишком велико.)
И последнее, но не менее важное: оно должно быть читаемым и легко расширяемым , БЕЗ оказывает какое-либо влияние на производительность ... Например, если кому-то нужны "восьмеричные значения", пожалуйста, обратитесь к строкам со словами "... можно расширить ..." - я думаю, что это должно быть очень простой задачей.
Я сосредоточился на производительности. Каждая «процедура обработки» (например, _f_money) может быть инкапсулирована, оптимизирована или заменена другими идеями в этом или других потоках без изменения «процедур подготовки» (анализа строк формата и создания функций), которые должны обрабатываться только один раз и в этом смысл не настолько критичен по производительности, как конверсионные вызовы тысяч номеров.
Для всех, кто предпочитает методы чисел:
Number.prototype.format_euro=( function(formatter){
return function(){ return formatter(this); }})
(Format_Numb( "%m €"));
var v_euro= (8192.3282).format_euro(); //results: 8.192,33 €
Number.prototype.format_hex= (function(formatter){
return function(){ return formatter(this); }})
(Format_Numb( "%4x"));
var v_hex= (4.3282).format_hex();
Хотя я что-то тестировал, в коде может быть много ошибок. Так что это не готовый модуль, а просто идея и отправная точка для не-js-экспертов, таких как я. Код содержит много и мало модифицированных идей из множества сообщений stackoverflow; извините, я не могу сослаться на них всех, но спасибо всем экспертам.
Set textbox's MultiLine property to True and EnterKeyBehavior to True.
пробовали ли вы включить элемент управления отформатированным текстом для текста? Не уверен, насколько хорошо он работает с VBA, но в VB6 я бы использовал именно его.