2012-05-03 28 views
1

すべての '項目'が数値であるか、すべての項目が英数字である限り、これは機能します。数値とアルファベットの 'items'があると、値が正しく入力されません。混合データ型のCSVファイルからデータを読み取る

ここにコードされています。これは動作します

ALB001,0 
ALB002,66 
10001,0 
10016,348 

public void updateInventory() 
{ 
    try 
    { 
     if (File.Exists(inventoryUpdateDirectory + "inventoryUpdate.csv")) 
     { 
      csvReader csv = new csvReader(); 
      DataTable inventory = csv.read(inventoryUpdateDirectory + "inventoryUpdate.csv"); 
      //int test = inventory.Rows.Count; 
      string sql = ""; 

      foreach (DataRow inventoryItem in inventory.Rows) 
      { 
       try 
       { 
        sql = " Update Inventory set OnHand = " + inventoryItem[1] + " WHERE Sku = '" + inventoryItem[0].ToString().Trim() + "'"; 
        //executeSQL(sql); 
       } 
       catch { } 
      } 

      File.Delete(inventoryUpdateDirectory + "inventoryUpdate.csv"); 
     } 
     else 
     { 
      writeToFile("fileDoesntExist", inventoryUpdateDirectory + "error.txt"); 
     } 
    } 
    catch { } 
} 

ここでは、読み込むファイルです

ALB001,0 
ALB002,66 

これは動作します:

10001,0 
10016,348 

これは動作しません。

ALB001,0 
ALB002,66 
10001,0 
10016,348 

それはALB001

CSVにおける最初の「列」の値を持つ必要があり、空の{}

+  inventoryItem[0] {} object {System.DBNull} 

としてinventoryItem配列を記入します文字数を含めることができるため、常に文字列として扱う必要があります.2番目の '列'は常に数字になります。

誰かがこれを理解するのを手伝ってくれますか?

私は文字列としてキャストするためにsqlクエリを編集する必要があると思いますが、わかりません。

CSVリーダーEDIT:以下の例では

namespace CSV 
{ 
    public class csvReader 
    { 
     public DataTable read(string strFileName) 
     { 
      OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OleDb.4.0; Data Source = " + System.IO.Path.GetDirectoryName(strFileName) + "; Extended Properties = \"Text;HDR=NO;FMT=Delimited\""); 
      conn.Open(); 
      string strQuery = "SELECT * FROM [" + System.IO.Path.GetFileName(strFileName) + "]"; 
      OleDbDataAdapter adapter = new OleDbDataAdapter(strQuery, conn); 
      DataSet ds = new DataSet("CSV File"); 
      adapter.Fill(ds); 
      return ds.Tables[0]; 
     } 

     public DataTable read(string strFileName, bool firstRowHeaders) 
     { 
      string hdr = "NO"; 
      if (firstRowHeaders) { hdr = "YES"; } 

      OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OleDb.4.0; Data Source = " + System.IO.Path.GetDirectoryName(strFileName) + "; Extended Properties = \"Text;HDR=" + hdr + ";FMT=Delimited\""); 
      conn.Open(); 
      string strQuery = "SELECT * FROM [" + System.IO.Path.GetFileName(strFileName) + "]"; 
      OleDbDataAdapter adapter = new OleDbDataAdapter(strQuery, conn); 
      DataSet ds = new DataSet("CSV File"); 
      adapter.Fill(ds); 
      return ds.Tables[0]; 
     } 
    } 
} 
+0

インラインSQLを使用せず、パラメータを使用してDataTypesを定義します。 – Zachary

+0

これは、もはやここにいない別の開発者によって行われました。書き直しは現時点では選択肢ではありません。 –

+0

csvReaderとは何ですか?問題がそこから始まることはほぼ確実です。 – Steve

答えて

1

問題は明らかにCsvReaderクラスにあります。ソースコードを添付していないので、コンテンツでそのデータテーブルを満たしていない理由を知ることは難しく、私ができることは推測です。

私はCodeProjectのからこのCSVリーダーを使用するためにあなたを示唆することによってあなたを助けるためにしようとします:それはループしながら、シンプルを使用してファイルの行を反復することができますよう http://www.codeproject.com/Articles/86973/C-CSV-Reader-and-Writer

あなたはデータテーブルで作業する必要はありません。 。あなたが更新し、適切なキャスティングを行うそして、LINQ

var data = (from line in File.ReadAllLines(fileName).AsParallel() 
      select line.Split(',')).ToList(); 

でCSVを読み取ることができ

using (CsvReader reader = new CsvReader(FilePath, Encoding.Default)) 
{ 
    while (reader.ReadNextRecord()) 
    { 
      sql = " Update Inventory set OnHand = " + reader.Fields[1] + " WHERE Sku = '" + reader.Fields[0] + "'"; 
    } 
} 
+0

OPをcsvReaderクラスで更新しました。 –

+0

投稿したコードによれば、CSVの生成方法をあまり制御することはできません。私は私の答えで提案したものにCsvReaderを置き換えることを勧めます。それは信頼性が高く、非常に高速であり、最も重要なことは、csvファイルを読む方法を完全に制御できることです。他の人のように強くお勧めします。明示的なSQLクエリを使用するのではなく、パラメータを使用することを強くお勧めします。あなたのアプリケーションはSQLインジェクションに非常に晒されています –

+0

私はこれを書き直すことができれば私は完全に同意します(私が使っているものはすべて文、パラメータなどを使っています)。私はちょうど上記の人に耳を傾ける必要があります。あなたが投稿した例を見て、私がそれを素早く処理できるかどうかを見てみましょう。 :) –

0

、私はそれは常に文字列を期待すべきSQLを伝えるために、ONHAND値の周りに単一引用符を追加しました。 "@パラメータ"を使用するようにSQL文を変更し、値をインラインで割り当てる方が良いでしょう。

sql = " Update Inventory set OnHand = '" + inventoryItem[1] + "' WHERE Sku = '" + inventoryItem[0].ToString().Trim() + "'"; 
+0

これは修正されませんでした。OnHandは常に数字になります.Sku(数字は1つ)は数字またはアルファベットの数字になります。それは以前と同じ問題です。=( –

0

:あなたのコードは次のようになります。

+0

これは、この新しいオブジェクトを扱うために既存のコードを書き直すのに多くの時間を費やす必要がありますか?私は、既存のコードベースを動作させる最も単純なソリューションを探しています。私はまだasp.netのノブでもあり、これは私にこの既存のものを書き換える動揺を与える。 –

+0

カンマを使用した分割はCSV仕様に準拠していません。たとえば、最初の列の値にコンマが含まれている場合は、2列ではなく3列の結果が生成されます。ただし、csv-complaintコードに変換するには、行を安全に分割するmehtodを呼び出します。 Line.Split call –

+0

私は、データテーブルを満たすためのリストがあるので、数分かかることがわかります。また、それは多くのクリーナーだろう。 –

1

これは古い質問であり、このような問題を解決するために多くのことを試したので、解決策を提供すると思いました。私はC#を使用していますが、VBライブラリを継承することができ、TextFieldParserライブラリはこれを非常にうまく処理します。私のデータでは、すべての列が同じ数の列になりますが、インポートされる列の数はわかりません。いくつかの列はカンマを含みますが、引用符 ""で囲まれていません。 DataTableを作成した後、すべての列を文字列にキャストして、後で型を検証します。最初にDataTableを作成するために使用するファイルのヘッダ行も削除します。これが誰かを助けることができれば幸いです

私が働いていた何のデータ例:

ヘッダ1、ヘッダ2、Header3
A、123、
B、123、
C、A、someDataが、その後 いくつかのより多くのデータ

私が最終的に思いついた解決策は、これが素晴らしいです。

using Microsoft.VisualBasic.FileIO; 

     private static DataTable GetDataTableFromCsv(string path) 
     { 
      var dataTable = new DataTable("ImportData"); 
      var rows = File.ReadAllLines(path); 
      var columns = rows[0].Split(','); 
      foreach (var column in columns) 
      { 
       dataTable.Columns.Add(new DataColumn(column.Trim(), typeof(string))); 
      } 
      using (var parser = new TextFieldParser(path)) 
      { 
       parser.Delimiters = new[] { "," }; 
       while (true) 
       { 
        var parts = parser.ReadFields(); 
        dataTable.Rows.Add(parts); 
        if (parser.EndOfData) break; 
       } 
      } 
      dataTable.Rows[0].Delete(); 
      return dataTable; 
     } 
+1

助けてください。ありがとう –

関連する問題