質問

Excelからデータをインポートして処理するC#/。Netジョブがあります。クライアントがファイルをドロップして処理します(元のファイルを制御できないため重要です)。

OleDbライブラリを使用してデータセットを埋めます(そのコードを書くのは嫌いです。まじめな話、.Net開発者がそれ以上書くのを恐れるコードはありますか?)。ファイルには30829300、30071500などの数字が含まれています。これらの列のデータ型は「テキスト」です

これらの数値は、データをインポートするときに科学表記法に変換されます。とにかくこれを防ぐ方法はありますか?

-クリス

役に立ちましたか?

解決

OleDbライブラリは、多くの場合、Excelスプレッドシートのデータを台無しにします 。これは主に、各列の最初の8つのセルの値から各列の型で guessing をすべて固定型列レイアウトに強制するためです。推測が間違っている場合は、数字列が科学表記に変換されてしまいます。 Blech!

これを回避するには、OleDbをスキップして、シートを直接自分で読んでください。これを行うには、ExcelのCOMインターフェイス(これもblech!)、またはサードパーティの.NET Excel互換リーダーを使用します。 SpreadsheetGear は、このようなライブラリの1つであり、適切に機能し、ExcelのCOMインターフェイスに非常によく似たインターフェイスを備えています。

他のヒント

この問題の回避策の1つは、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/

この接続文字列の使用:

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

Excel 2010では、次のことに気付きました。 OLEDB SELECTの実行時にExcelファイルが開いている場合、保存されたファイルの値ではなく、現在のバージョンのセルが取得されます。さらに、長い数値、10進数値、および日付に対して返される文字列値は次のようになります。

5.0130370071e+012
4.08
36808

ファイルが開いていない場合、返される値は次のとおりです。

5013037007084
£4.08
Monday, October 09, 2000

Open XML SDK 2.0 Productivity Toolを使用して実際の.XSLXファイルを見ると(または単にファイルを解凍して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が問題を引き起こしているとは限りません。

「番号」が大きい列のテキスト形式ではなく、Zip形式を選択するのが最も簡単な方法であることがわかりました。

読みながらフィールドの値を(int)または(Int64)にキャストしようとしましたか?

GoogleでIMEX = 1接続文字列オプションとTypeGuessRowsレジストリ設定を調べます。 実際、リーダーは最初の数行(デフォルトでは8行)を見て列のデータ型を推測するため、これを簡単に回避する方法はありません。行にすべての数字が含まれている場合、運が悪いです。

過去に使用した残念な回避策は、HDR = NO接続文字列オプションを使用し、TypeGuessRowsレジストリ設定値を1に設定して、最初の行を有効なデータとして読み取ってデータ型を決定することです。 、ヘッダーではなく。 それはハックですが、動作します。コードは最初の行(ヘッダーを含む)をテキストとして読み取り、それに応じてデータ型を設定します。

レジストリの変更は苦痛ですが(常に可能とは限りません)、後で元の値に戻すことをお勧めします。

インポートデータにヘッダー行がない場合、代替オプションはファイルを前処理し、問題の列の各数字の前に '文字を挿入することです。これにより、列データがテキストとして扱われます。

全体として、これを回避するためのハックがたくさんありますが、絶対確実なものはありません。

これと同じ問題がありましたが、Excel COMインターフェイスやサードパーティソフトウェアに頼らずに回避できました。少し処理オーバーヘッドがかかりますが、私にとっては機能しているようです。

  1. 最初にデータを読み込んで列名を取得します
  2. 次に、これらの各列で新しいDataSetを作成し、各DataTypesをstringに設定します。
  3. この新しいデータに再度データを読み込みます データセット。 Voila-科学者 表記はなくなり、すべてが文字列として読み込まれます。

これを説明するコードをいくつか紹介します。また、追加のボーナスとして、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.
                        }
                    }
                }
            }
        }
    }
}

この状態をグーグルで検索しました。 ここに私の解任手順があります

  • テンプレートExcelファイルの場合

1形式のExcelの列としてのテキスト 2-数値のエラー警告を無効にするマクロを記述します-&gt;テキスト変換

  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。への着信データを解析しようとします...

これに対する答えが誰かにあったかどうか知りたいです。私はすべてインターウェブを行ったり来たりして、IMEXとHDRのすべての組み合わせを試しました。 IMEX = 1は、日付、通貨、および一般的な数値を抽出して管理した唯一のものです。しかし、大きな数字は依然として科学的であることが示されています。ファイルを読むだけで、スプレッドシート、レジストリを変更できます。サードパーティはオプションではありません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top