Excelからデータをインポートして処理するC#/。Netジョブがあります。クライアントがファイルをドロップして処理します。元のファイルを制御することはできません。
OleDbライブラリを使用してデータセットを埋めます。ファイルには、30829300、30071500などの番号が含まれています。これらの列のデータ型は「テキスト」です。
データをインポートすると、これらの数値は科学的記数法に変換されます。これを防ぐ方法はありますか?
この問題の回避策の 1 つは、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/
OleDb ライブラリは、多くの場合、Excel スプレッドシートのデータを台無しにします。これは主に、各列の最初の 8 つのセルの値から各列の型を推測して、すべてを固定型の列レイアウトに強制するためです。推測が間違っている場合は、数字の文字列が科学的表記法に変換されてしまいます。ブリーチ!
これを回避するには、OleDb をスキップして、自分でシートを直接読むことをお勧めします。これは、Excel の COM インターフェイス (これも blech!)、またはサードパーティの .NET Excel 互換リーダーを使用して行うことができます。 SpreadsheetGearは、適度に機能するライブラリの 1 つであり、Excel の COM インターフェイスと非常によく似たインターフェイスを備えています。
この接続文字列の使用:
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 インターフェイスやサード パーティのソフトウェアに頼らずに回避できました。少し処理のオーバーヘッドがかかりますが、私にとってはうまくいっているようです。
これを説明するコードを次に示します。追加のボーナスとして、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.
}
}
}
}
}
}
}
私は別の場所から1つの解決策を得ましたが、それは私にとって完璧に機能しました。コードを変更する必要はありません。「数値」や「テキスト」などの他の書式設定ではなく、Excel 列のセルを「一般」に書式設定するだけで、Select * from [$Sheet1] または Select Column_name from [$Sheet1] が読み取られます。 9桁を超える大きな数値でも完全に
私はこの状態をグーグルで検索しました..これが私の解決策です
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に解析しようとします....