Как читать данные файла Excel с помощью С#?
Как читать файл 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();
}
}
}
}
Ответы
Ответ 1
OK
Одна из наиболее сложных концепций, связанных с программированием Excel VSTO, заключается в том, что вы не ссылаетесь на ячейки, такие как массив, Worksheet[0][0]
не даст вам ячейку A1, она будет выходить из строя на вас. Даже когда вы вводите A1, когда Excel открыт, вы фактически вводите данные в Range A1. Поэтому вы ссылаетесь на ячейки как Named Ranges. Вот пример:
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
является параметризованным, а С# еще не поддерживает их.
Что касается кода очистки, я опубликую это, когда я получу работу завтра, у меня нет кода со мной, но это очень шаблонный. Вы просто закрываете и освобождаете объекты в порядке, в котором вы их создали. Вы не можете использовать блок 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. Это в С#, потому что я не писал его. VB.NET хорошо выполняет параметры параметров, С# не делает этого, следовательно, 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);
Это помогает понять параметры.
P.S. Я один из тех странных людей, которым нравится изучать автоматизацию COM. Весь этот код обрабатывался с помощью инструмента, который я написал для работы, который требовал от меня обрабатывать более 1000 таблиц из лаборатории каждый понедельник.
Ответ 2
Вы можете использовать сборку Microsoft.Office.Interop.Excel
для обработки файлов excel.
- Щелкните правой кнопкой мыши на своем проекте и перейдите к
Add reference
. Добавить
Сборка Microsoft.Office.Interop.Excel.
- Включить
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);
Ответ 3
Почему вы не создаете 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();
}
Ответ 4
Прежде всего, важно знать, что вы подразумеваете под "открыть файл Excel для чтения и скопировать его в буфер обмена..."
Это очень важно, потому что есть много способов сделать это, в зависимости от того, что вы намереваетесь сделать. Позвольте мне объяснить:
-
Если вы хотите прочитать набор данных и скопировать их в буфер обмена, и вы знаете формат данных (например, имена столбцов), я предлагаю вам использовать OleDbConnection, чтобы открыть файл, таким образом вы можете обрабатывать содержимое файла xls в виде таблицы базы данных, чтобы вы могли читать данные с помощью инструкции SQL и обрабатывать данные по своему усмотрению.
-
Если вы хотите выполнять операции с данными с помощью объектной модели Excel, откройте ее так, как вы начали.
-
Некоторое время можно рассматривать файл xls как своего рода csv файл, есть такие инструменты, как File Helpers, которые позволяют вам обрабатывать и открывать файл xls простым способом, сопоставляя структуру с произвольным объектом.
Другим важным моментом является то, в какой версии Excel находится файл.
У меня, к сожалению, я говорю, сильный опыт работы с автоматизацией Office во всех отношениях, даже если он ограничен такими понятиями, как Application Automation, Data Management и Plugins, и, как правило, я предлагаю только в качестве последнего средства использовать автоматизацию Excel или Автоматизация Office для чтения данных; просто если нет лучших способов выполнить эту задачу.
Работа с автоматизацией может быть тяжелой в производительности, с точки зрения стоимости ресурсов, может включать в себя другие проблемы, связанные, например, с безопасностью, и многое другое, и последнее, но не по крайней мере, работа с COM-взаимодействием не так "бесплатна".
Поэтому мое предложение - подумать и проанализировать ситуацию в ваших потребностях, а затем сделать лучший способ.
Ответ 5
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);
}
Это сработало для меня. Пожалуйста, попробуйте и дайте мне знать для запросов.
Ответ 6
Используйте OLEDB Connection для связи с файлами 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();
}
Данные вывода будут храниться в наборе данных, используя объект набора данных, с которым вы можете легко получить доступ к данным.
Надеюсь, это может быть полезно
Ответ 7
Чтение и чтение файлов Excel без Excel в системе u'r
- Загрузите и добавьте 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); }}
Ответ 8
Используйте Open 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;
}
Ответ 9
Рекомендуемым способом чтения файлов Excel на стороне сервера является Open XML.
Обмен несколькими ссылками -
https://msdn.microsoft.com/en-us/library/office/hh298534.aspx
https://msdn.microsoft.com/en-us/library/office/ff478410.aspx
https://msdn.microsoft.com/en-us/library/office/cc823095.aspx
Ответ 10
public void excelRead(string sheetName)
{
Excel.Application appExl = new Excel.Application();
Excel.Workbook workbook = null;
try
{
string methodName = "";
Excel.Worksheet NwSheet;
Excel.Range ShtRange;
//Opening Excel file(myData.xlsx)
appExl = new Excel.Application();
workbook = appExl.Workbooks.Open(sheetName, Missing.Value, ReadOnly: false);
NwSheet = (Excel.Worksheet)workbook.Sheets.get_Item(1);
ShtRange = NwSheet.UsedRange; //gives the used cells in sheet
int rCnt1 = 0;
int cCnt1 = 0;
for (rCnt1 = 1; rCnt1 <= ShtRange.Rows.Count; rCnt1++)
{
for (cCnt1 = 1; cCnt1 <= ShtRange.Columns.Count; cCnt1++)
{
if (Convert.ToString(NwSheet.Cells[rCnt1, cCnt1].Value2) == "Y")
{
methodName = NwSheet.Cells[rCnt1, cCnt1 - 2].Value2;
Type metdType = this.GetType();
MethodInfo mthInfo = metdType.GetMethod(methodName);
if (Convert.ToString(NwSheet.Cells[rCnt1, cCnt1 - 2].Value2) == "fn_AddNum" || Convert.ToString(NwSheet.Cells[rCnt1, cCnt1 - 2].Value2) == "fn_SubNum")
{
StaticVariable.intParam1 = Convert.ToInt32(NwSheet.Cells[rCnt1, cCnt1 + 3].Value2);
StaticVariable.intParam2 = Convert.ToInt32(NwSheet.Cells[rCnt1, cCnt1 + 4].Value2);
object[] mParam1 = new object[] { StaticVariable.intParam1, StaticVariable.intParam2 };
object result = mthInfo.Invoke(this, mParam1);
StaticVariable.intOutParam1 = Convert.ToInt32(result);
NwSheet.Cells[rCnt1, cCnt1 + 5].Value2 = Convert.ToString(StaticVariable.intOutParam1) != "" ? Convert.ToString(StaticVariable.intOutParam1) : String.Empty;
}
else
{
object[] mParam = new object[] { };
mthInfo.Invoke(this, mParam);
NwSheet.Cells[rCnt1, cCnt1 + 5].Value2 = StaticVariable.outParam1 != "" ? StaticVariable.outParam1 : String.Empty;
NwSheet.Cells[rCnt1, cCnt1 + 6].Value2 = StaticVariable.outParam2 != "" ? StaticVariable.outParam2 : String.Empty;
}
NwSheet.Cells[rCnt1, cCnt1 + 1].Value2 = StaticVariable.resultOut;
NwSheet.Cells[rCnt1, cCnt1 + 2].Value2 = StaticVariable.resultDescription;
}
else if (Convert.ToString(NwSheet.Cells[rCnt1, cCnt1].Value2) == "N")
{
MessageBox.Show("Result is No");
}
else if (Convert.ToString(NwSheet.Cells[rCnt1, cCnt1].Value2) == "EOF")
{
MessageBox.Show("End of File");
}
}
}
workbook.Save();
workbook.Close(true, Missing.Value, Missing.Value);
appExl.Quit();
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(ShtRange);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(NwSheet);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(workbook);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(appExl);
}
catch (Exception)
{
workbook.Close(true, Missing.Value, Missing.Value);
}
finally
{
GC.Collect();
GC.WaitForPendingFinalizers();
System.Runtime.InteropServices.Marshal.CleanupUnusedObjectsInCurrentContext();
}
}
//code for reading excel data in datatable
public void testExcel(string sheetName)
{
try
{
MessageBox.Show(sheetName);
foreach(Process p in Process.GetProcessesByName("EXCEL"))
{
p.Kill();
}
//string fileName = "E:\\inputSheet";
Excel.Application oXL;
Workbook oWB;
Worksheet oSheet;
Range oRng;
// creat a Application object
oXL = new Excel.Application();
// get WorkBook object
oWB = oXL.Workbooks.Open(sheetName);
// get WorkSheet object
oSheet = (Microsoft.Office.Interop.Excel.Worksheet)oWB.Sheets[1];
System.Data.DataTable dt = new System.Data.DataTable();
//DataSet ds = new DataSet();
//ds.Tables.Add(dt);
DataRow dr;
StringBuilder sb = new StringBuilder();
int jValue = oSheet.UsedRange.Cells.Columns.Count;
int iValue = oSheet.UsedRange.Cells.Rows.Count;
// get data columns
for (int j = 1; j <= jValue; j++)
{
oRng = (Microsoft.Office.Interop.Excel.Range)oSheet.Cells[1, j];
string strValue = oRng.Text.ToString();
dt.Columns.Add(strValue, System.Type.GetType("System.String"));
}
//string colString = sb.ToString().Trim();
//string[] colArray = colString.Split(':');
// get data in cell
for (int i = 2; i <= iValue; i++)
{
dr = dt.NewRow();
for (int j = 1; j <= jValue; j++)
{
oRng = (Microsoft.Office.Interop.Excel.Range)oSheet.Cells[i, j];
string strValue = oRng.Text.ToString();
dr[j - 1] = strValue;
}
dt.Rows.Add(dr);
}
if(StaticVariable.dtExcel != null)
{
StaticVariable.dtExcel.Clear();
StaticVariable.dtExcel = dt.Copy();
}
else
StaticVariable.dtExcel = dt.Copy();
oWB.Close(true, Missing.Value, Missing.Value);
oXL.Quit();
MessageBox.Show(sheetName);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
}
}
//code for class initialize
public static void startTesting(TestContext context)
{
Playback.Initialize();
ReadExcel myClassObj = new ReadExcel();
string sheetName="";
StreamReader sr = new StreamReader(@"E:\SaveSheetName.txt");
sheetName = sr.ReadLine();
sr.Close();
myClassObj.excelRead(sheetName);
myClassObj.testExcel(sheetName);
}
//code for test initalize
public void runValidatonTest()
{
DataTable dtFinal = StaticVariable.dtExcel.Copy();
for (int i = 0; i < dtFinal.Rows.Count; i++)
{
if (TestContext.TestName == dtFinal.Rows[i][2].ToString() && dtFinal.Rows[i][3].ToString() == "Y" && dtFinal.Rows[i][4].ToString() == "TRUE")
{
MessageBox.Show(TestContext.TestName);
MessageBox.Show(dtFinal.Rows[i][2].ToString());
StaticVariable.runValidateResult = "true";
break;
}
}
//StaticVariable.dtExcel = dtFinal.Copy();
}
Ответ 11
Я бы рекомендовал вам использовать таблицу Bytescout.
https://bytescout.com/products/developer/spreadsheetsdk/bytescoutspreadsheetsdk.html
Я попробовал его с Monodevelop в Unity3D, и это довольно просто. Проверьте этот пример кода, чтобы узнать, как работает библиотека:
https://bytescout.com/products/developer/spreadsheetsdk/read-write-excel.html