Чтение десятичного значения из ячейки Excel (на C #)

#c# #.net #excel #openxml-sdk

#c# #.net #преуспеть #openxml-sdk

Вопрос:

При считывании значений из ячеек Excel, содержащих десятичные дроби, я сталкиваюсь со следующей проблемой: если я ввожу 9,95 в ячейку в Excel, CellValue.InnerText в C # возвращается «9,9499999999999993»

Как я могу получить фактическое введенное значение, означающее «9,95», зная, что код, который пытается получить эти значения, заранее не знает, что это десятичное или действительно число.

Комментарии:

1. Вы видели эту страницу msdn ? Прокрутите вниз до раздела «Извлечение значения».

2. @gunr2171 У меня есть, и он не отвечает на вопрос

3. @pnuts почему вы даете мне урок по арифметике с плавающей запятой, когда все, что я хочу, это получить (текстовое) значение так, как его отображает Excel

4. Вы путаете фактическое значение, которое было введено (пользователем, 9,95), со значением, которое хранит Excel (9,94999993)

5. Если Excel не может быть уверен, почему при изменении формата для отображения 20 знаков после запятой он по-прежнему будет отображать 9.95000000000000000000, а не сохраненное значение 9.9499999999993?

Ответ №1:

Excel хранит значения в виде чисел с плавающей запятой двойной точности, поэтому часто то, что вы вводите в Excel, не может быть точно сохранено в виде чисел с плавающей запятой.

http://blogs.office.com/2008/04/10/understanding-floating-point-precision-aka-why-does-excel-give-me-seemingly-wrong-answers/

Если вы действительно хотите посмотреть, как Excel хранит ваши значения, вы можете изменить расширение .xlsx на .zip, открыть его и просмотреть файлы. Это вся информация, хранящаяся в вашей ячейке:

 <sheetData>
    <row r="1" spans="1:1" x14ac:dyDescent="0.3">
        <c r="A1">
            <v>9.9499999999999993</v> 
        </c>
    </row>
</sheetData>
 

Excel можно было бы создать для хранения точных значений, которые вы вводите (сохраняя их как десятичные, а не с плавающей запятой), но арифметические операции были бы намного медленнее, поскольку все вычисления выполнялись бы программно, а не аппаратно.

Комментарии:

1. Я понимаю, что оно хранится в виде числа с плавающей запятой, но я хочу знать, есть ли в OPENXML SDK способ получить значение так, как оно отображается пользователю

2. @Luis Ferrao: Я не верю, что это так. OpenXML SDK не имеет встроенной логики, он просто предоставляет необработанный объект, в который вы можете десериализовать файлы xlsx и манипулировать ими. Вероятно, вы могли бы выяснить это самостоятельно, изучив ширину столбца и стиль, применяемые к ячейке, чтобы выяснить, сколько цифр должно отображаться.

Ответ №2:

Вы не можете получить фактическое значение, введенное для числовой записи. Я не верю, что это где-то хранится. Значение, которое вы видите, — это сохраненное значение; вы также можете получить отображаемое значение (в VBA это будет значение .Текстовое свойство ячейки), но я не думаю, что вы сможете добраться до введенного значения.

Проблема связана с врожденной невозможностью представления определенных десятичных чисел в двоичном формате.

См . Также эту критику формата Excel XML

Комментарии:

1. Есть ли способ получить это .Text в C # / OPENXML SDK?

2. @LuisFerrao Я не знаю. Оно должно быть сохранено в XML-документе, представляющем рабочую книгу, по крайней мере, в виде форматирования, поэтому оно должно быть как-то доступно, но я не знаком с C # / OPENXML SDK

3. @LuisFerrao Посмотрите здесь критический анализ формата Excel xml: codeproject.com/Articles/20246 /…

4. Я принимаю это, потому что последняя ссылка из codeproject действительно информативна, спасибо

5. @LuisFerrao Спасибо. Я добавлю эту ссылку к своему ответу

Ответ №3:

Поскольку Excel хранит данные в формате с плавающей запятой, попробуйте выполнить синтаксический анализ из float:

 string curSep = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator;
string value = CellValue.InnerText.Replace(".", curSep);
value = value.Replace(",", curSep);
return float.Parse(value);
 

Работает ли это?