3

Excel シートからデータを読み取るために Microsoft.ACE.OLEDB.12.0 プロバイダーを使用しています。私はデータを取得するために使用OleDbDataReaderGetValue()ています。最初の行/行 (複数可能) は文字列ヘッダーであり、スキップできません。次は小数点以下0桁に設定された数値データですが、そのうちの1つを選択すると、正しい小数点形式でバーに表示されます。

この混合データを、Excel の棒グラフのように完全な元の 10 進数形式で読み取るにはどうすればよいですか? Excelシートの設定を変更できません。

ここに画像の説明を入力

これが私のコードです:

using System.Data.OleDb;

    namespace ConsoleApplication2
    {
        class Program
        {
            static void Main(string[] args)
            {
                string query = "SELECT * FROM [List1$]";
                string connString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\Temp\Test.xls;Extended Properties=""Excel 12.0;HDR=NO;IMEX=1""";
                using (OleDbConnection connection = new OleDbConnection(connString))
                {
                    connection.Open();
                    using (OleDbCommand command = new OleDbCommand(query, connection))
                    {
                        using (OleDbDataReader reader = command.ExecuteReader())
                        {
                            while (reader.Read())
                            {
                                object value = reader.GetValue(0);
                            }
                        }
                    }
                }
            }
        }
    }
4

2 に答える 2

2

経験から、おそらくあなたがやろうとしている最善の方法は以下です。私はいつもExcelファイルで問題を抱えていて、データを読んでいました。これが、データ転送メカニズムとしての Excel を軽蔑する理由です。

私は、すべての「銀行データ」を Excel で取得する会社で働いていました。間違っていることが証明されれば幸いです。

ノート。GetValue(0) が実行されたら、ウォッチを設定します。おそらく文字列であることがわかります。しかし、それが何を考えているかを判断してから、「Get」メソッドを少し調整することができます。同様に、値が「文字列」の場合、GetValue(0) を GetString(0) に変更できます。

while (reader.Read())
{
    Decimal tryParseResultDec;
    object value = reader.GetValue(0);
    if !(Decimal.TryParse(value, out tryParseResultDec))
    {
        throw new ArgumentException(string.Format("Unable to parse '{0}'.", value));   
    }

}

追加提案。

「0」、「1」、「2」などの代わりに、通常、クラスの先頭にいくつかのプライベート const を配置して、列が何であるかを示します。

private const int EXCEL_COLUMN_TOTAL_AMOUNT = 0;

(あなたはそのようなことをするかもしれません、そしてあなたは例を単純に保ちました)

追加のヒント:

それが機能する方法は、Excelがデータの最初の行を見て、データ型を見て、それを同じ列の残りの行に使用することだと思います。「各行のデータ型を確認してください」とは言わないと思います。したがって、あなたの難問。

ヘッダー行がないと言うと、A のすべての行のデータ型を A1 で調べます。ヘッダー行があると言うと、A のすべての行のデータ型を A2 で調べます。

于 2013-02-22T14:45:32.280 に答える
2

接続文字列で使用HDR=YESしてみて、最初の行のスキップを停止します。

string connString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\Temp\Test.xls;Extended Properties=""Excel 12.0;HDR=YES;IMEX=1""";

[アップデート]

使用することをお勧めする回避策は、ファイルを2回読み取ることです(同じ方法で):

  1. まず、ヘッダー行を取得します。おそらく、後でデータ構造に必要になります
  2. 2 回目の読み取りでは、ヘッダーをスキップして行を読み取ります。

これは次のようになります。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.OleDb;
using System.Data;
using System.IO;

class Program
{
    static void Main(string[] args)
    {
        // the Excel file
        string file = @"c:\Temp\Test.xls";

        if (!File.Exists(file))
        {
            Console.WriteLine("File not found.");
            return;
        }

        // DataTable bonus! :)
        System.Data.DataTable dt = new System.Data.DataTable();

        IEnumerable<List<object>> header = new List<List<object>>();
        IEnumerable<List<object>> rows = new List<List<object>>();

        // read the header first
        header = GetData(file, true);

        // read the rows
        rows = GetData(file, false);

        // add the columns
        foreach (var column in header.First())
        {
            dt.Columns.Add(column.ToString());
        }

        // add the rows
        foreach (var row in rows)
        {
            dt.Rows.Add(row.ToArray());
        }

        // now you may use the dt DataTable for your purpose
    }

    /// <summary>
    /// Read from the Excel file
    /// </summary>
    /// <param name="file">The path to the Excel file</param>
    /// <param name="readHeader">True if you want to read the header, 
    /// False if you want to read the rows</param>
    /// <returns></returns>
    private static IEnumerable<List<object>> GetData(string file, bool readHeader)
    {
        string query = "SELECT * FROM [List1$]";
        string connString = @"Provider=Microsoft.ACE.OLEDB.12.0;" +
            @"Data Source=" + file + @";Extended Properties=""Excel 12.0 Xml;HDR=NO;IMEX="
            + ((readHeader) ? "1" : "0") + @";""";
        using (OleDbConnection connection = new OleDbConnection(connString))
        {
            connection.Open();
            using (OleDbCommand command = new OleDbCommand(query, connection))
            {
                using (OleDbDataReader reader = command.ExecuteReader())
                {
                    bool isHeaderRead = false;
                    while (reader.Read())
                    {
                        if (readHeader && isHeaderRead)
                        { break; }
                        isHeaderRead = true;
                        List<object> values = new List<object>();
                        for (int i = 0; i < reader.FieldCount; i++)
                        {
                            values.Add(reader.GetValue(i));
                        }
                        yield return values;
                    }
                }
            }
        }
    }
}
于 2013-02-22T14:02:12.887 に答える