it-swarm.com.ru

Как читать данные из файла Excel с помощью C #?

Как прочитать файл Excel с помощью C #? Я открываю файл 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();
            }
        }
    }
}
61
ankush

В порядке,

Одна из наиболее сложных концепций программирования VSTO в Excel заключается в том, что вы не ссылаетесь на ячейки как на массив, Worksheet[0][0] не выдаст вам ячейку A1, а выдаст ошибку. Даже когда вы печатаете в A1, когда Excel открыт, вы фактически вводите данные в диапазон 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

     }

Возможно, есть лучший способ, но это сработало для меня.

Причина, по которой вам нужно использовать Value2, а не Value, заключается в том, что свойство Value параметризовано, а C # их пока не поддерживает.

Что касается кода очистки, я опубликую, что когда я завтра приступлю к работе, у меня нет кода, но он очень стандартный. Вы просто закрываете и отпускаете объекты в обратном порядке, в котором вы их создали. Вы не можете использовать блок Using(), потому что Excel.Application или Excel.Workbook не реализуют IDisposable, и если вы не выполните очистку, у вас останутся висящие объекты 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 дважды подряд, вы бежите, крича из комнаты!

Что касается вашего вопроса, вы можете попробовать следующее:

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

Вот еще один пример, вдохновленный этим сайт :

 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. Весь этот код был написан на инструменте, который я написал для работы и который требовал от меня обработки более 1000 электронных таблиц из лаборатории каждый понедельник.

85
Chris

Вы можете использовать Microsoft.Office.Interop.Excel Assembly для обработки файлов Excel. 

  1. Щелкните правой кнопкой мыши по вашему проекту и перейдите к Add reference. Добавьте сборку Microsoft.Office.Interop.Excel. 
  2. Включите using Microsoft.Office.Interop.Excel;, чтобы использовать Assembly.

Вот пример кода: 

    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();
}
17
Chathuranga Chandrasekara

Прежде всего, важно знать, что вы подразумеваете под «открыть файл Excel для чтения и скопировать его в буфер обмена ...»

Это очень важно, потому что есть много способов сделать это в зависимости от того, что вы собираетесь делать. Позволь мне объяснить:

  1. Если вы хотите прочитать набор данных и скопировать их в буфер обмена, и вы знаете формат данных (например, имена столбцов), я предлагаю вам использовать OleDbConnection, чтобы открыть файл, таким образом, вы можете обрабатывать файл xls. содержимое как таблица базы данных, так что вы можете читать данные с помощью инструкции SQL и обрабатывать данные по своему усмотрению.

  2. Если вы хотите выполнять операции с данными с помощью объектной модели Excel, откройте их так, как вы начали.

  3. Иногда можно рассматривать файл xls как своего рода файл csv. Существуют такие инструменты, как File Helpers , которые позволяют простым способом обрабатывать и открывать файл xls путем сопоставления структуры с произвольным объектом.

Еще один важный момент - в какой версии 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 File Reader & Writer без Excel в вашей системе

  • Загрузите и добавьте dll для проекта NPOI u'r.
  • Используя этот код, чтобы прочитать файл 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

Использовать Открыть XML .

Вот некоторый код для обработки электронной таблицы с определенной вкладкой или именем листа и вывода ее в что-то вроде CSV. (Я выбрал трубу вместо запятой).

Хотелось бы, чтобы было проще получить значение из ячейки, но я думаю, что это то, с чем мы застряли. Вы можете видеть, что я ссылаюсь на документы MSDN, где я получил большую часть этого кода. Это то, что Microsoft рекомендует.

    /// <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