Научная запись при импорте из Excel в .Net

У меня есть задание C# /. Net, которое импортирует данные из Excel, а затем обрабатывает их. Наш клиент отправляет файлы, а мы их обрабатываем. У меня нет контроля над исходным файлом.

Я использую библиотеку OleDb для пополнения набора данных. Файл содержит числа, например 30829300, 30071500 и т. д. Тип данных для этих столбцов - «Текст».

Когда я импортирую данные, эти числа преобразуются в научное представление. Есть ли способ предотвратить это?

В какой тип данных вы импортируете строку чисел?

scottm 10.01.2009 01:13
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
9
1
14 280
10
Перейти к ответу Данный вопрос помечен как решенный

Ответы 10

Я обнаружил, что самый простой способ - выбрать формат Zip, а не текстовый формат для столбцов с большими «числами».

Как я уже сказал выше, у меня нет контроля над файлом. Это создает клиент.

ChrisDiRulli 10.01.2009 00:43

Вы пробовали преобразовать значение поля в (int) или, возможно, (Int64), когда вы его читаете?

Я не «читаю» файл, это делает OleDb API. Я просто вызываю метод fill в OleDbDataAdapter и передаю DataSet. Затем набор данных заполняется сочными и вкусными данными.

ChrisDiRulli 10.01.2009 00:54

Является ли набор данных строго типизированным, так что это поле ожидает числа?

palehorse 10.01.2009 00:55

Нет, это не строго типизированный.

ChrisDiRulli 10.01.2009 01:04

Попробуйте создать для него набор данных со строгой типизацией. Это должно правильно его преобразовать.

palehorse 10.01.2009 01:31
Ответ принят как подходящий

Библиотека OleDb будут чаще всего портит ваши данные в электронной таблице Excel. Это в значительной степени потому, что он заставляет все в макете столбца фиксированного типа, угадывать в типе каждого столбца из значений в первых 8 ячейках в каждом столбце. Если он угадает неправильно, вы получите цепочку цифр, преобразованную в научную нотацию. Блеч!

Чтобы избежать этого, вам лучше пропустить OleDb и прочитать лист самостоятельно. Вы можете сделать это с помощью COM-интерфейса Excel (тоже бесполезно!) Или стороннего .NET Excel-совместимого ридера. Таблица - одна из таких библиотек, которая работает достаточно хорошо и имеет интерфейс, очень похожий на COM-интерфейс Excel.

Найдите параметр строки подключения IMEX = 1 и параметр реестра TypeGuessRows в Google. По правде говоря, нет простого способа обойти это, потому что читатель определяет типы данных столбца, просматривая первые несколько строк (по умолчанию 8). Если строки содержат все числа, вам не повезло.

Неудачный обходной путь, который я использовал в прошлом, - использовать параметр строки подключения HDR = NO и установить для параметра реестра TypeGuessRows значение 1, что заставляет его читать первую строку как допустимые данные для определения своего типа данных, а не заголовок. Это взлом, но он работает. Код считывает первую строку (содержащую заголовок) как текст, а затем соответственно устанавливает тип данных.

Изменение реестра - это боль (и не всегда возможно), но я бы порекомендовал впоследствии восстановить исходное значение.

Если в ваших данных импорта нет строки заголовка, то альтернативным вариантом является предварительная обработка файла и вставка символа 'перед каждым из чисел в неправильном столбце. Это приводит к тому, что данные столбца обрабатываются как текст.

В общем, есть множество уловок, чтобы обойти это, но ничего действительно надежного.

Я пробовал свойство IMEX = 1 .. строка con: "Provider = Microsoft.ACE.OLEDB.12.0; Data Source = # FILEPATH #; Extended Properties = 'Excel 12.0 Xml; HDR = NO; IMEX = 1", но значение выглядит как 2,13123219999999E + 18 ...........

dankyy1 07.03.2011 18:33

Вы также должны установить запись реестра TypeGuessRows. Как я уже сказал, это неудачный взлом.

Andrew Rollings 15.03.2011 15:38

У меня была такая же проблема, но я смог обойти ее, не прибегая к COM-интерфейсу Excel или стороннему программному обеспечению. Это связано с небольшими накладными расходами на обработку, но, похоже, работает для меня.

  1. Сначала прочтите данные, чтобы получить имена столбцов
  2. Затем создайте новый DataSet с каждым из этих столбцов, установив для каждого из их DataTypes значение string.
  3. Прочтите данные еще раз в этот новый набор данных. Вуаля - научный обозначение теперь исчезло, и все читается как строка.

Вот код, который это иллюстрирует, и в качестве дополнительного бонуса это даже StyleCopped!

public void ImportSpreadsheet(string path)
{
    string extendedProperties = "Excel 12.0;HDR=YES;IMEX=1";
    string connectionString = string.Format(
        CultureInfo.CurrentCulture,
        "Provider=Microsoft.ACE.OLEDB.12.0;Data Source = {0};Extended Properties=\"{1}\"",
        path,
        extendedProperties);

    using (OleDbConnection connection = new OleDbConnection(connectionString))
    {
        using (OleDbCommand command = connection.CreateCommand())
        {
            command.CommandText = "SELECT * FROM [Worksheet1$]";
            connection.Open();

            using (OleDbDataAdapter adapter = new OleDbDataAdapter(command))
            using (DataSet columnDataSet = new DataSet())
            using (DataSet dataSet = new DataSet())
            {
                columnDataSet.Locale = CultureInfo.CurrentCulture;
                adapter.Fill(columnDataSet);

                if (columnDataSet.Tables.Count == 1)
                {
                    var worksheet = columnDataSet.Tables[0];

                    // Now that we have a valid worksheet read in, with column names, we can create a
                    // new DataSet with a table that has preset columns that are all of type string.
                    // This fixes a problem where the OLEDB provider is trying to guess the data types
                    // of the cells and strange data appears, such as scientific notation on some cells.
                    dataSet.Tables.Add("WorksheetData");
                    DataTable tempTable = dataSet.Tables[0];

                    foreach (DataColumn column in worksheet.Columns)
                    {
                        tempTable.Columns.Add(column.ColumnName, typeof(string));
                    }

                    adapter.Fill(dataSet, "WorksheetData");

                    if (dataSet.Tables.Count == 1)
                    {
                        worksheet = dataSet.Tables[0];

                        foreach (var row in worksheet.Rows)
                        {
                            // TODO: Consume some data.
                        }
                    }
                }
            }
        }
    }
}

штопать! Разве такая проблема не заставляет вас рвать волосы?

Andrew Garrison 09.03.2011 00:33

Я погуглил об этом состоянии .. Вот мои шаги решения

  • Для файла Excel шаблона

Столбец Excel в формате 1 как текст 2- написать макрос для отключения предупреждений об ошибках для числа -> преобразование текста

  Private Sub Workbook_BeforeClose(Cancel As Boolean)
Application.ErrorCheckingOptions.BackgroundChecking = Ture
End Sub
Private Sub Workbook_Open()
Application.ErrorCheckingOptions.BackgroundChecking = False
End Sub
  • О выделенном коде

3- при чтении данных для импорта попробуйте разобрать входящие данные в Int64 или Int32 ....

Одним из способов решения этой проблемы является изменение оператора select вместо SELECT *, сделайте следующее:

"SELECT Format([F1], 'General Number')  From [Sheet1$]"
 -or-
"SELECT Format([F1], \"#####\")  From [Sheet1$]"

Однако это приведет к взрыву, если ваши ячейки содержат более 255 символов, со следующей ошибкой: «Многошаговая операция OLE DB вызвала ошибки. Проверьте каждое значение статуса OLE DB, если доступно. Никакой работы не выполнялось».

К счастью, мой клиент не заботился об ошибке в этом сценарии.

На этой странице также есть много хороших вещей, которые можно попробовать: http://www.dicks-blog.com/archives/2004/06/03/external-data-mixed-data-types/

Привет. Я использовал это исправление, и, похоже, оно исправило некоторые проблемы для меня. Проблема в том, что кажется, что каждое число округляется так, чтобы последние две цифры были нулями. Например, 12345678 становится 12345600. Кто-нибудь знает, как я могу это исправить?

Loogawa 11.03.2013 18:38

Если вы посмотрите на фактический файл .XSLX с помощью инструмента повышения производительности Open XML SDK 2.0 (или просто распакуйте файл и просмотрите XML в блокноте), вы увидите, что Excel 2007 фактически хранит необработанные данные в научном формате.

Например, 0,00001 сохраняется как 1.0000000000000001E-5.

<x:c r = "C18" s = "11" xmlns:x = "http://schemas.openxmlformats.org/spreadsheetml/2006/main">
  <x:v>1.0000000000000001E-5</x:v>
</x:c>

Глядя на ячейку в Excel, она отображается как 0,00001 как в ячейке, так и в строке формул. Так что не всегда верно, что OleDB вызывает проблему.

Используя эту строку подключения:

Provider=Microsoft.ACE.OLEDB.12.0; data source = {0}; Extended Properties=\"Excel 12.0;HDR=NO;IMEX=1\"

с Excel 2010 я заметил следующее. Если файл Excel открыт при запуске OLEDB SELECT, вы получите текущую версию ячеек, а не сохраненные значения файла. Кроме того, строковые значения, возвращаемые для длинного числа, десятичного значения и даты, выглядят следующим образом:

5.0130370071e+012
4.08
36808

Если файл не открыт, возвращаются следующие значения:

5013037007084
£4.08
Monday, October 09, 2000

Я получил одно решение откуда-то еще, но оно отлично сработало для меня. Нет необходимости вносить какие-либо изменения в код, просто отформатируйте ячейки столбцов Excel как «Общие» вместо любого другого форматирования, такого как «число» или «текст», тогда даже «Выбрать * из [$ Sheet1]» или «Выбрать имя_столбца из [$ Sheet1] будет читать отлично даже с большими числовыми значениями более 9 цифр

Другие вопросы по теме