OK
Одной из наиболее сложных концепций программирования 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, у меня тоже нет этого кода.
Edit:
Как и было обещано, вот функции из 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);
Это помогает понять параметры.
P.S. Я один из тех странных людей, которым нравится изучать автоматизацию COM. Весь этот код был написан на основе инструмента, который я написал для работы и который требовал от меня обработки более 1000 электронных таблиц из лаборатории каждый понедельник.