В дополнение к комментариям Майка Розенблюма об использовании массивов, я хотел бы добавить, что я использую сам подход (массивы VSTO +), и когда я измерял его, фактическая скорость чтения была в пределах миллисекунд. Просто не забудьте отключить обработку событий и обновление экрана перед чтением / записью, и не забудьте снова включить ее после завершения операции.
Используя C #, вы можете создавать массивы на основе 1 точно так же, как это делает сам Excel VBA. Это очень полезно, особенно потому, что даже в VSTO, когда вы извлекаете массив из объекта Excel.Range, массив основывается на 1, поэтому сохранение ориентированных на Excel массивов на основе 1 помогает избежать необходимости всегда проверять, является ли массив является единичным или основанным на нуле. (Если позиция столбца в массиве имеет для вас значение, то иметь дело с массивами на основе 0 и 1 может быть настоящей болью).
Вообще чтение Excel.Range в массив выглядело бы примерно так:
var myArray = (object[,])range.Value2;
В моем варианте записи массива Майка Розенблюма используется массив на основе 1, подобный этому:
int[] lowerBounds = new int[]{ 1, 1 };
int[] lengths = new int[] { rowCount, columnCount };
var myArray =
(object[,])Array.CreateInstance(typeof(object), lengths, lowerBounds);
var dataRange = GetRangeFromMySources();
// this example is a bit too atomic; you probably want to disable
// screen updates and events a bit higher up in the call stack...
dataRange.Application.ScreenUpdating = false;
dataRange.Application.EnableEvents = false;
dataRange = dataRange.get_Resize(rowCount, columnCount);
dataRange.set_Value(Excel.XlRangeValueDataType.xlRangeValueDefault, myArray);
dataRange.Application.ScreenUpdating = true;
dataRange.Application.EnableEvents = true;
Чтобы ответить на несколько иной вопрос: не используйте тип float для представления денежных значений. Он вас укусит . Вместо этого используйте тип с основанием 10, например BigDecimal
, или целочисленный тип, например int
или long
(представляющий квант вашего значения - пенни, например, в валюте США).
Вы не сможете сохранить точное значение - например, 123,45 в виде числа с плавающей запятой, и математические операции с этим значением (например, умножение на налоговый процент) приведут к ошибкам округления.
Пример с этой страницы:
float a = 8250325.12f;
float b = 4321456.31f;
float c = a + b;
System.out.println(NumberFormat.getCurrencyInstance().format(c));
// prints $12,571,782.00 (wrong)
BigDecimal a1 = new BigDecimal("8250325.12");
BigDecimal b1 = new BigDecimal("4321456.31");
BigDecimal c1 = a1.add(b1);
System.out.println(NumberFormat.getCurrencyInstance().format(c1));
// prints $12,571,781.43 (right)
Вы не хотите гадить ошибками, когда дело касается денег.
Что касается исходного вопроса, я уже давно не касался Java, но я знаю, что ' Я бы хотел держаться подальше от регулярных выражений, чтобы выполнять такую работу. Я считаю, что это рекомендуется; это может вам помочь. Не проверено; предостережение разработчика.
try {
String string = NumberFormat.getCurrencyInstance(Locale.GERMANY)
.format(123.45);
Number number = NumberFormat.getCurrencyInstance(locale)
.parse("$123.45");
// 123.45
if (number instanceof Long) {
// Long value
} else {
// too large for long - may want to handle as error
}
} catch (ParseException e) {
// handle
}
Ищите регион с правилами, которые соответствуют тому, что вы ожидаете увидеть. Если вы не можете найти один, используйте несколько последовательно или создайте свой собственный пользовательский NumberFormat .
Я бы также подумал о том, чтобы заставить пользователей вводить значения в едином каноническом формате. 123.45 и 123.456 выглядят на мой вкус слишком похожими, и по вашим правилам могут привести к значениям, различающимся в 1000 раз. Вот как теряются миллионы .
канонический формат. 123.45 и 123.456 выглядят на мой вкус слишком похожими, и по вашим правилам могут привести к значениям, различающимся в 1000 раз. Вот как теряются миллионы . канонический формат. 123.45 и 123.456 выглядят на мой вкус слишком похожими, и по вашим правилам могут привести к значениям, различающимся в 1000 раз. Вот как теряются миллионы .Быстрый «грязный» взлом может быть следующим:
String input = input.replaceAll("\.,",""); // remove *any* , or .
long amount = Long.parseLong(input);
BigDecimal bd = BigDecimal.valueOf(amount).movePointLeft(2);
//then you could use:
bd.floatValue();
//but I would seriously recommended that you don't use floats for monetary amounts.
Обратите внимание, что это будет работать, только если ввод будет в форме ###. 00, то есть с ровно двумя десятичными знаками . Например, input == "10,022"
сломает этот довольно наивный код.
Альтернативой является использование конструктора BigDecimal (String)
, но вам нужно будет преобразовать эти евро номера стиля для использования '.' в качестве десятичного разделителя, помимо удаления разделителей тысяч для обоих.