Научная запись при импорте из Excel в .Net - PullRequest
7 голосов
/ 10 января 2009

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

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

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

-Крис

Ответы [ 10 ]

5 голосов
/ 13 октября 2011

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

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

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

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

На этой странице также есть куча хороших вещей: http://www.dicks -blog.com / архив / 2004/06/03 / внешних данные смешанных типов данных /

3 голосов
/ 23 апреля 2013

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

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
3 голосов
/ 10 января 2009

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

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

1 голос
/ 27 марта 2012

Если вы посмотрите на фактический файл .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 вызывает проблему.

0 голосов
/ 08 марта 2011

Мне интересно знать, получил ли кто-нибудь ответ на этот вопрос. Я пробежался по Интернету и перепробовал все комбинации IMEX и HDR. IMEX = 1 - единственный, с которым мне удалось извлечь значения даты, валюты и общих чисел. Но большие числа все еще показывают как научный. Мне нужно только читать файлы и менять электронные таблицы, реестр, сторонние не вариант.

0 голосов
/ 08 марта 2011

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

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

1-форматный столбец Excel в виде текста 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 ....

0 голосов
/ 09 сентября 2010

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

  1. Сначала прочитайте данные, чтобы получить имена столбцов
  2. Затем создайте новый DataSet с каждым из этих столбцов, установив для каждого из их DataTypes строку.
  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.
                        }
                    }
                }
            }
        }
    }
}
0 голосов
/ 18 февраля 2009

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

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

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

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

Итак, в общем, есть куча хаков, чтобы обойти это, но ничего по-настоящему надежного.

0 голосов
/ 10 января 2009

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

0 голосов
/ 10 января 2009

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

...