2016-04-30 12 views
-1

私はExcelファイルからデータをアップロードするためにEpplusライブラリを使用しています。私が使用しているコードは、最初の行が列であれば標準のform.ieを持つExcelファイルすべてのデータは列に対応しています。今、私は定期的に取得しています。異なる構造を持ち、読み込めないファイルをExcelします。asp.netでExcelファイルを読むには

私が望むものは3行目ですwan only Region位置IDとその値。次に、7行目は列、8〜15は値です。最後に17行目は18〜20列目です。これらのデータを別々のデータセットにロードする方法 コードは以下の通りです。 拡張方法

public static DataSet Exceltotable(this string path) 
     { 
      DataSet ds = null; 
      using (var pck = new OfficeOpenXml.ExcelPackage()) 
      { 
       try 
       { 
        using (var stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 
        { 
         pck.Load(stream); 
        } 
        ds = new DataSet(); 
        var wss = pck.Workbook.Worksheets; 
        //////////////////////////////////// 
        //Application app = new Application(); 
        //app.Visible = true; 
        //app.Workbooks.Add(""); 
        //app.Workbooks.Add(@"c:\MyWork\WorkBook1.xls"); 
        //app.Workbooks.Add(@"c:\MyWork\WorkBook2.xls"); 
        //for (int i = 2; i <= app.Workbooks.Count; i++) 
        //{ 
        // for (int j = 1; j <= app.Workbooks[i].Worksheets.Count; j++) 
        // { 
        //  Worksheet ws = app.Workbooks[i].Worksheets[j]; 
        //  ws.Copy(app.Workbooks[1].Worksheets[1]); 
        // } 
        //} 

        /////////////////////////////////////////////////// 

        //for(int s=0;s<5;s++) 
        //{ 
        foreach (var ws in wss) 
        { 
         System.Data.DataTable tbl = new System.Data.DataTable(); 
         bool hasHeader = true; // adjust it accordingly(i've mentioned that this is a simple approach) 
         string ErrorMessage = string.Empty; 
         foreach (var firstRowCell in ws.Cells[1, 1, 1, ws.Dimension.End.Column]) 
         { 

          tbl.Columns.Add(hasHeader ? firstRowCell.Text : string.Format("Column {0}", firstRowCell.Start.Column)); 

         } 
         var startRow = hasHeader ? 2 : 1; 
         for (var rowNum = startRow; rowNum <= ws.Dimension.End.Row; rowNum++) 
         { 
          var wsRow = ws.Cells[rowNum, 1, rowNum, ws.Dimension.End.Column]; 
          var row = tbl.NewRow(); 
          foreach (var cell in wsRow) 
          { 
           //modifed by faras 
           if (cell.Text != null) 
           { 
            row[cell.Start.Column - 1] = cell.Text; 
           } 
          } 
          tbl.Rows.Add(row); 
          tbl.TableName = ws.Name; 
         } 
         DataTable dt = RemoveEmptyRows(tbl); 
         ds.Tables.Add(dt); 
        } 
       } 
       catch (Exception exp) 
       { 


       } 
       return ds; 
      } 
     } 
+0

あなたが表示するファイルは**修復**とマークされているのが普通ですか? –

答えて

2

ユーザーがアップロードするテンプレートを提供している場合は、スプレッドシート内の名前付き範囲を使用してこのテンプレートを軽減できます。とにかくExcelでプログラムを操作するときは、ユーザーの操作だけでなく、独自のスプレッドシートを変更するときに役立ちます。

範囲を指定する方法はわかっているかもしれませんが、完全性のためにhere's how to name a rangeです。

コードでスプレッドシートを使用している場合は、[yourworkbook].Names["yourNamedRange"]を使用して範囲への参照を取得できます。単一行のセルで、行または列のインデックスを参照する必要がある場合は、.Start.Rowまたは.Start.Columnを使用できます。

何かの名前付き範囲 - 特定の値、列、ヘッダー行、データセットが始まる行を含むセル - を追加します。行または列のインデックスが必要な場合は、便利な変数名を割り当てます。これは、あなたのスプレッドシートにあらゆる種類の「マジックナンバー」を持つことからあなたを守ります。あなた(またはあなたのユーザー)は何も壊さずにかなり動き回ることができます。

構造があまりにも変更された場合、機能しません。また、ブックやワークシートの保護機能を使用して、タブ、行、列などの構造を誤って変更できないようにすることもできます。


これは私がこれを学んだときに私が最後の週末に取り組んでいたテストから大まかに取られています。それはちょうど「こんにちはの世界」なので、私はそれを合理化して完璧にしようとはしていませんでした。 (私は1つを読んでいない、スプレッドシートを取り込むに取り組んでいたので、私が行くように、私はちょうど性質を学んでいる。)

// Open the workbook 
using (var package = new ExcelPackage(new FileInfo("PriceQuoteTemplate.xlsx"))) 
{ 
    // Get the worksheet I'm looking for 
    var quoteSheet = package.Workbook.Worksheets["Quote"]; 

    //If I wanted to get the text from one named range 
    var cellText = quoteSheet.Workbook.Names["myNamedRange"].Text 

    //If I wanted to get the cell's value as some other type 
    var cellValue = quoteSheet.Workbook.Names["myNamedRange"].GetValue<int>(); 

    //If I had a named range and I wanted to loop through the rows and get 
    //values from certain columns 
    var myRange = quoteSheet.Workbook.Names["rangeContainingRows"]; 

    //This is a named range used to mark a column. So instead of using a 
    //magic number, I'll read from whatever column has this named range. 
    var someColumn = quoteSheet.Workbook.Names["columnLabel"].Start.Column; 

    for(var rowNumber = myRange.Start.Row; rowNumber < myRange.Start.Row + myRange.Rows; rowNumber++) 
    { 
     var getTheTextForTheRowAndColumn = quoteSheet.Cells(rowNumber, someColumn).Text 
    } 

それについて移動するために、よりエレガントな方法があるかもしれません。私はこれを自分で使い始めました。しかし、スプレッドシート上で特定の名前付き範囲を見つけるように指示してから、マジック行や列番号の代わりにその範囲の行番号または列番号を使用します。

範囲は1つのセル、1つの行、または1つの列であっても、潜在的に大きな領域になる可能性があります。だから私は.Start.Rowを使用しています。言い換えれば、範囲内のの最初のセルの行を私に与えてください。範囲に複数の行がある場合、.Rowsプロパティは行数を示し、その数がわかります。つまり、誰かがコードを壊さずに行を挿入することさえできます。

+0

スムーズなC#スニペットを投稿できますか – peter

+0

確かに - 私はこれを自分自身で考え出していますが、私は基本的な考え方を捉えたものを投稿しました。 –

関連する問題