web-dev-qa-db-ja.com

C#を使用してExcelファイルのデータを読み取る方法は?

C#を使用してExcelファイルを読み取る方法Excelファイルを読み取り用に開いてクリップボードにコピーし、メール形式を検索しますが、その方法がわかりません。

FileInfo finfo;
Excel.ApplicationClass ExcelObj = new Excel.ApplicationClass();
ExcelObj.Visible = false;

Excel.Workbook theWorkbook;
Excel.Worksheet worksheet;

if (listView1.Items.Count > 0)
{
    foreach (ListViewItem s in listView1.Items)
    {
        finfo = new FileInfo(s.Text);
        if (finfo.Extension == ".xls" || finfo.Extension == ".xlsx" || finfo.Extension == ".xlt" || finfo.Extension == ".xlsm" || finfo.Extension == ".csv")
        {
            theWorkbook = ExcelObj.Workbooks.Open(s.Text, 0, true, 5, "", "", true, Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, false, false);

            for (int count = 1; count <= theWorkbook.Sheets.Count; count++)
            {
                worksheet = (Excel.Worksheet)theWorkbook.Worksheets.get_Item(count);
                worksheet.Activate();
                worksheet.Visible = false;
                worksheet.UsedRange.Cells.Select();
            }
        }
    }
}
63
ankush

OK、

Excel VSTOプログラミングについて理解するのが難しい概念の1つは、配列のようなセルを参照しないことです。Worksheet[0][0]はセルA1を提供せず、エラーが発生します。 Excelが開いているときにA1に入力しても、実際には範囲A1にデータを入力しています。したがって、セルを名前付き範囲と呼びます。以下に例を示します。

Excel.Worksheet sheet = workbook.Sheets["Sheet1"] as Excel.Worksheet; 
Excel.Range range = sheet.get_Range("A1", Missing.Value)

次のように入力できます。

range.Text // this will give you the text the user sees
range.Value2 // this will give you the actual value stored by Excel (without rounding)

このようなことをしたい場合:

Excel.Range range = sheet.get_Range("A1:A5", Missing.Value)

if (range1 != null)
     foreach (Excel.Range r in range1)
     {
         string user = r.Text
         string value = r.Value2

     }

より良い方法があるかもしれませんが、これは私のために働いています。

ValueではなくValue2を使用する必要があるのは、Valueプロパティがパラメータ化されており、C#がまだそれらをサポートしていないためです。

クリーンアップコードについては、明日仕事に着いたときに投稿します。コードを持っていませんが、非常に定型的なものです。オブジェクトを作成したのと逆の順序で閉じて離すだけです。 Excel.ApplicationまたはExcel.WorkbookはIDisposableを実装していないため、Using()ブロックを使用できません。クリーンアップしないと、Excelオブジェクトがハングしたままになります。メモリ内。

注意:

  • Visibilityプロパティを設定しない場合、Excelは表示されません。これはユーザーを混乱させる可能性がありますが、データを単にリッピングする場合は、おそらく十分です
  • OleDbを使用することもできますが、それでも機能します。

それがあなたが始められることを望みます、あなたがさらなる説明が必要かどうか私に知らせてください。完全に投稿します

完全なサンプルを次に示します。

using System;
using System.IO;
using System.Reflection;
using NUnit.Framework;
using ExcelTools = Ms.Office;
using Excel = Microsoft.Office.Interop.Excel;

namespace Tests
{
    [TestFixture]
    public class ExcelSingle
    {
        [Test]
        public void ProcessWorkbook()
        {
            string file = @"C:\Users\Chris\Desktop\TestSheet.xls";
            Console.WriteLine(file);

            Excel.Application Excel = null;
            Excel.Workbook wkb = null;

            try
            {
                Excel = new Excel.Application();

                wkb = ExcelTools.OfficeUtil.OpenBook(Excel, file);

                Excel.Worksheet sheet = wkb.Sheets["Data"] as Excel.Worksheet;

                Excel.Range range = null;

                if (sheet != null)
                    range = sheet.get_Range("A1", Missing.Value);

                string A1 = String.Empty;

                if( range != null )
                    A1 = range.Text.ToString();

                Console.WriteLine("A1 value: {0}", A1);

            }
            catch(Exception ex)
            {
                //if you need to handle stuff
                Console.WriteLine(ex.Message);
            }
            finally
            {
                if (wkb != null)
                    ExcelTools.OfficeUtil.ReleaseRCM(wkb);

                if (Excel != null)
                    ExcelTools.OfficeUtil.ReleaseRCM(Excel);
            }
        }
    }
}

明日、ExcelToolsから関数を投稿しますが、私もそのコードを持っていません。

編集:約束どおり、必要なExcelToolsの関数を以下に示します。

public static Excel.Workbook OpenBook(Excel.Application excelInstance, string fileName, bool readOnly, bool editable,
        bool updateLinks) {
        Excel.Workbook book = excelInstance.Workbooks.Open(
            fileName, updateLinks, readOnly,
            Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
            Type.Missing, editable, Type.Missing, Type.Missing, Type.Missing,
            Type.Missing, Type.Missing);
        return book;
    }

public static void ReleaseRCM(object o) {
        try {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(o);
        } catch {
        } finally {
            o = null;
        }
    }

率直に言って、VB.NETを使用する場合、この機能ははるかに簡単です。私が書いていないので、C#で書かれています。 VB.NETはオプションパラメータを適切に実行しますが、C#はそうではないため、Type.Missingを使用します。 Type.Missingを2回続けて入力すると、部屋から叫び声が上がります!

あなたの質問に関しては、次のことを試すことができます:

http://msdn.Microsoft.com/en-us/library/Microsoft.office.interop.Excel.range.find(VS.80).aspx

会議から戻ったときに例を投稿します...乾杯

編集:ここに例があります

range = sheet.Cells.Find("Value to Find",
                                                 Type.Missing,
                                                 Type.Missing,
                                                 Type.Missing,
                                                 Type.Missing,
                                                 Excel.XlSearchDirection.xlNext,
                                                 Type.Missing,
                                                 Type.Missing, Type.Missing);

range.Text; //give you the value found

これに触発された別の例を次に示します site

 range = sheet.Cells.Find("Value to find", Type.Missing, Type.Missing,Excel.XlLookAt.xlWhole,Excel.XlSearchOrder.xlByColumns,Excel.XlSearchDirection.xlNext,false, false, Type.Missing);

パラメータを理解するのに役立ちます。

追伸私は、COMオートメーションの学習を楽しんでいる奇妙な人々の1人です。このコードはすべて、毎週月曜日にラボで作成した1000以上のスプレッドシートを処理する必要がある仕事用に作成したツールから生成されました。

85
Chris

Microsoft.Office.Interop.Excel Assemblyを使用して、Excelファイルを処理できます。

  1. プロジェクトを右クリックして、Add referenceに移動します。 Microsoft.Office.Interop.Excelアセンブリを追加します。
  2. using Microsoft.Office.Interop.Excel;を含めて、アセンブリを使用します。

サンプルコードは次のとおりです。

    using Microsoft.Office.Interop.Excel;

    //create the Application object we can use in the member functions.
    Microsoft.Office.Interop.Excel.Application _excelApp = new Microsoft.Office.Interop.Excel.Application();
    _excelApp.Visible = true;

    string fileName = "C:\\sampleExcelFile.xlsx";

    //open the workbook
    Workbook workbook = _excelApp.Workbooks.Open(fileName,
        Type.Missing, Type.Missing, Type.Missing, Type.Missing,
        Type.Missing, Type.Missing, Type.Missing, Type.Missing,
        Type.Missing, Type.Missing, Type.Missing, Type.Missing,
        Type.Missing, Type.Missing);

    //select the first sheet        
    Worksheet worksheet = (Worksheet)workbook.Worksheets[1];

    //find the used range in worksheet
    Range excelRange = worksheet.UsedRange;

    //get an object array of all of the cells in the worksheet (their values)
    object[,] valueArray = (object[,])excelRange.get_Value(
                XlRangeValueDataType.xlRangeValueDefault);

    //access the cells
    for (int row = 1;  row <= worksheet.UsedRange.Rows.Count; ++row)
    {
        for (int col = 1; col <= worksheet.UsedRange.Columns.Count; ++col)
        {
            //access each cell
            Debug.Print(valueArray[row, col].ToString());
        }
    }

    //clean up stuffs
    workbook.Close(false, Type.Missing, Type.Missing);
    Marshal.ReleaseComObject(workbook);

    _excelApp.Quit();
    Marshal.FinalReleaseComObject(_excelApp);
21
Green goblin

OleDbConnectionを作成しませんか?インターネットには多くの利用可能なリソースがあります。ここに例があります

OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+filename+";Extended Properties=Excel 8.0");
con.Open();
try
{
     //Create Dataset and fill with imformation from the Excel Spreadsheet for easier reference
     DataSet myDataSet = new DataSet();
     OleDbDataAdapter myCommand = new OleDbDataAdapter(" SELECT * FROM ["+listname+"$]" , con);
     myCommand.Fill(myDataSet);
     con.Close();
     richTextBox1.AppendText("\nDataSet Filled");

     //Travers through each row in the dataset
     foreach (DataRow myDataRow in myDataSet.Tables[0].Rows)
     {
          //Stores info in Datarow into an array
          Object[] cells = myDataRow.ItemArray;
          //Traverse through each array and put into object cellContent as type Object
          //Using Object as for some reason the Dataset reads some blank value which
          //causes a hissy fit when trying to read. By using object I can convert to
          //String at a later point.
          foreach (object cellContent in cells)
          {
               //Convert object cellContect into String to read whilst replacing Line Breaks with a defined character
               string cellText = cellContent.ToString();
               cellText = cellText.Replace("\n", "|");
               //Read the string and put into Array of characters chars
               richTextBox1.AppendText("\n"+cellText);
          }
     }
     //Thread.Sleep(15000);
}
catch (Exception ex)
{
     MessageBox.Show(ex.ToString());
     //Thread.Sleep(15000);
}
finally
{
     con.Close();
}

まず、「Excelファイルを読み取り用に開いてクリップボードにコピーする」という意味を理解することが重要です。

これは非常に重要です。なぜなら、あなたがやろうとしていることに応じてそれを行う方法はたくさんあるからです。説明させてください:

  1. データのセットを読み取ってクリップボードにコピーし、データ形式(列名など)がわかっている場合は、OleDbConnectionを使用してファイルを開くことをお勧めします。これにより、xlsファイルの内容をデータベーステーブルとして扱うことができるため、SQL命令でデータを読み取り、必要に応じてデータを扱うことができます。

  2. Excelオブジェクトモデルを使用してデータの操作を行う場合は、開始した方法で開きます。

  3. Xlsファイルを一種のcsvファイルとして扱うことができる場合、 File Helpers のようなツールがあります。これにより、任意の構造をマッピングすることにより、xlsファイルを簡単に処理して開くことができます。オブジェクト。

もう1つの重要な点は、ファイルがどのExcelバージョンであるかです。

残念ながら、アプリケーションオートメーション、データ管理、プラグインなどの概念に縛られている場合でも、あらゆる方法でOfficeオートメーションを使用した強力な経験があり、一般的には、最後の手段として、ExcelオートメーションまたはOfficeオートメーションを使用してデータの読み取り。そのタスクを達成するためのより良い方法がない場合だけです。

自動化を使用すると、リソースコストの点でパフォーマンスが高くなり、セキュリティなどに関連する他の問題が発生する可能性があります。最後になりましたが、COM相互運用の操作はそれほど「無料」ではありません。ニーズ内の状況を考えて分析し、より良い方法を取ることです。

5
Hoghweed
try
        {
            DataTable sheet1 = new DataTable("Excel Sheet");
            OleDbConnectionStringBuilder csbuilder = new OleDbConnectionStringBuilder();
            csbuilder.Provider = "Microsoft.ACE.OLEDB.12.0";
            csbuilder.DataSource = fileLocation;
            csbuilder.Add("Extended Properties", "Excel 12.0 Xml;HDR=YES");
            string selectSql = @"SELECT * FROM [Sheet1$]";
            using (OleDbConnection connection = new OleDbConnection(csbuilder.ConnectionString))
            using (OleDbDataAdapter adapter = new OleDbDataAdapter(selectSql, connection))
            {
                connection.Open();
                adapter.Fill(sheet1);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }

これは私のために働いた。試してみて、クエリについて教えてください。

4
Vishal Kotak

OLEDB接続を使用して、Excelファイルと通信します。より良い結果が得られます

using System.Data.OleDb;



                string physicalPath = "Your Excel file physical path";
                OleDbCommand cmd = new OleDbCommand();
                OleDbDataAdapter da = new OleDbDataAdapter();
                DataSet ds = new DataSet();
                String strNewPath = physicalPath;
                String connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + strNewPath + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=2\"";
                String query = "SELECT * FROM [Sheet1$]"; // You can use any different queries to get the data from the Excel sheet
                OleDbConnection conn = new OleDbConnection(connString);
                if (conn.State == ConnectionState.Closed) conn.Open();
                try
                {
                    cmd = new OleDbCommand(query, conn);
                    da = new OleDbDataAdapter(cmd);
                    da.Fill(ds);

                }
                catch
                {
                    // Exception Msg 

                }
                finally
                {
                    da.Dispose();
                    conn.Close();
                }

出力データはデータセットに保存され、データセットオブジェクトを使用して簡単にデータにアクセスできます。これが役立つことを願っています

1
Suganth G

Excelを使用しないExcelファイルリーダーおよびライター

  • NPOI u'rプロジェクトのdllをダウンロードして追加します。
  • このコードを使用してExcelファイルを読み取ります。

            using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
               XSSFWorkbook XSSFWorkbook = new XSSFWorkbook(file);
            }
            ISheet objxlWorkSheet = XSSFWorkbook.GetSheetAt(0);
            int intRowCount = 1;
            int intColumnCount = 0;
            for (; ; )
            {
                IRow Row = objxlWorkSheet.GetRow(intRowCount);
                if (Row != null)
                {
                    ICell Cell = Row.GetCell(0);
                    ICell objCell = objxlWorkSheet.GetRow(intRowCount).GetCell(intColumnCount); }}
    
0
RandyMohan

Open XML を使用します。

特定のタブまたはシート名を持つスプレッドシートを処理し、CSVなどにダンプするコードを次に示します。 (コンマの代わりにパイプを選択しました)。

セルから値を取得する方が簡単だったらいいのにと思いますが、これが私たちが行き詰まっていることだと思います。このコードのほとんどを入手したMSDNドキュメントを参照していることがわかります。それがマイクロソフトの推奨事項です。

    /// <summary>
    /// Got code from: https://msdn.Microsoft.com/en-us/library/office/gg575571.aspx
    /// </summary>
    [Test]
    public void WriteOutExcelFile()
    {
        var fileName = "ExcelFiles\\File_With_Many_Tabs.xlsx";
        var sheetName = "Submission Form"; // Existing tab name.
        using (var document = SpreadsheetDocument.Open(fileName, isEditable: false))
        {
            var workbookPart = document.WorkbookPart;
            var sheet = workbookPart.Workbook.Descendants<Sheet>().FirstOrDefault(s => s.Name == sheetName);
            var worksheetPart = (WorksheetPart)(workbookPart.GetPartById(sheet.Id));
            var sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();

            foreach (var row in sheetData.Elements<Row>())
            {
                foreach (var cell in row.Elements<Cell>())
                {
                    Console.Write("|" + GetCellValue(cell, workbookPart));
                }
                Console.Write("\n");
            }
        }
    }

    /// <summary>
    /// Got code from: https://msdn.Microsoft.com/en-us/library/office/hh298534.aspx
    /// </summary>
    /// <param name="cell"></param>
    /// <param name="workbookPart"></param>
    /// <returns></returns>
    private string GetCellValue(Cell cell, WorkbookPart workbookPart)
    {
        if (cell == null)
        {
            return null;
        }

        var value = cell.CellFormula != null
            ? cell.CellValue.InnerText 
            : cell.InnerText.Trim();

        // If the cell represents an integer number, you are done. 
        // For dates, this code returns the serialized value that 
        // represents the date. The code handles strings and 
        // Booleans individually. For shared strings, the code 
        // looks up the corresponding value in the shared string 
        // table. For Booleans, the code converts the value into 
        // the words TRUE or FALSE.
        if (cell.DataType == null)
        {
            return value;
        }
        switch (cell.DataType.Value)
        {
            case CellValues.SharedString:

                // For shared strings, look up the value in the
                // shared strings table.
                var stringTable =
                    workbookPart.GetPartsOfType<SharedStringTablePart>()
                        .FirstOrDefault();

                // If the shared string table is missing, something 
                // is wrong. Return the index that is in
                // the cell. Otherwise, look up the correct text in 
                // the table.
                if (stringTable != null)
                {
                    value =
                        stringTable.SharedStringTable
                            .ElementAt(int.Parse(value)).InnerText;
                }
                break;

            case CellValues.Boolean:
                switch (value)
                {
                    case "0":
                        value = "FALSE";
                        break;
                    default:
                        value = "TRUE";
                        break;
                }
                break;
        }
        return value;
    }
0
Jess